Compare commits
	
		
			488 Commits
		
	
	
		
			sleek-1.1.
			...
			slix-1.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8adc8fa2ba | ||
| 
						 | 
					9efa909dfc | ||
| 
						 | 
					7f21fdbe26 | ||
| 
						 | 
					f9c7fa92ea | ||
| 
						 | 
					e75a160d52 | ||
| 
						 | 
					170bd51387 | ||
| 
						 | 
					2ce931cb7a | ||
| 
						 | 
					84eddd2ed2 | ||
| 
						 | 
					d0ad25745a | ||
| 
						 | 
					55be23a6da | ||
| 
						 | 
					75ba283572 | ||
| 
						 | 
					f7164d35d2 | ||
| 
						 | 
					4afbb0322b | ||
| 
						 | 
					7bce1ecc8a | ||
| 
						 | 
					bbce16d526 | ||
| 
						 | 
					c29fc39ef1 | ||
| 
						 | 
					8335c08782 | ||
| 
						 | 
					04bff00171 | ||
| 
						 | 
					f3e31baf04 | ||
| 
						 | 
					a2852eb249 | ||
| 
						 | 
					f1e6d6b0a9 | ||
| 
						 | 
					116a33ba51 | ||
| 
						 | 
					b8d7b9520c | ||
| 
						 | 
					0305ce66b7 | ||
| 
						 | 
					474405ab90 | ||
| 
						 | 
					4415d3be1a | ||
| 
						 | 
					058c530787 | ||
| 
						 | 
					766d0dfd40 | ||
| 
						 | 
					ac31913a65 | ||
| 
						 | 
					d34ddf33db | ||
| 
						 | 
					eb4e09b0ca | ||
| 
						 | 
					ce085bf4f4 | ||
| 
						 | 
					990113f8e7 | ||
| 
						 | 
					aa022204ee | ||
| 
						 | 
					c1f23b566b | ||
| 
						 | 
					45f7cb8bda | ||
| 
						 | 
					bdb1f66ac9 | ||
| 
						 | 
					d5b1904ebb | ||
| 
						 | 
					b6b0e82dec | ||
| 
						 | 
					632b7b4afe | ||
| 
						 | 
					0ef3fa2703 | ||
| 
						 | 
					8da269de88 | ||
| 
						 | 
					93ce318259 | ||
| 
						 | 
					997928de91 | ||
| 
						 | 
					83d00a5913 | ||
| 
						 | 
					bf5d7c83af | ||
| 
						 | 
					c66a4d4097 | ||
| 
						 | 
					e112e86475 | ||
| 
						 | 
					e034b31d6b | ||
| 
						 | 
					18a4978456 | ||
| 
						 | 
					17464b10a4 | ||
| 
						 | 
					6fb3ecd414 | ||
| 
						 | 
					c214e4f037 | ||
| 
						 | 
					2ee05d9616 | ||
| 
						 | 
					f795ac02e3 | ||
| 
						 | 
					6e8235544c | ||
| 
						 | 
					6e35948276 | ||
| 
						 | 
					4da870fd19 | ||
| 
						 | 
					cd7ff685fb | ||
| 
						 | 
					1e4944d47e | ||
| 
						 | 
					e68135f59f | ||
| 
						 | 
					6408c5a747 | ||
| 
						 | 
					115fe954ac | ||
| 
						 | 
					3d243f7da5 | ||
| 
						 | 
					ea5615f236 | ||
| 
						 | 
					69da1c1d7c | ||
| 
						 | 
					e85fa4203e | ||
| 
						 | 
					506ca69917 | ||
| 
						 | 
					8ac0ecdf40 | ||
| 
						 | 
					dbd8115557 | ||
| 
						 | 
					74b4ea20bf | ||
| 
						 | 
					11fbaa4241 | ||
| 
						 | 
					8fd0d7c993 | ||
| 
						 | 
					1450d36377 | ||
| 
						 | 
					06358d0665 | ||
| 
						 | 
					2b3b86e281 | ||
| 
						 | 
					92e4bc752a | ||
| 
						 | 
					ffb2e05f21 | ||
| 
						 | 
					1e2665df19 | ||
| 
						 | 
					4d063e287e | ||
| 
						 | 
					44f02fb3ab | ||
| 
						 | 
					f6b3a0c6cf | ||
| 
						 | 
					8b36e918e8 | ||
| 
						 | 
					957c635fb7 | ||
| 
						 | 
					4027927c6e | ||
| 
						 | 
					62eefdbd6a | ||
| 
						 | 
					225e07eb64 | ||
| 
						 | 
					1207c81ab5 | ||
| 
						 | 
					565da65ccd | ||
| 
						 | 
					47fbd4cead | ||
| 
						 | 
					1b9b4199e8 | ||
| 
						 | 
					b5930ca958 | ||
| 
						 | 
					423974f90d | ||
| 
						 | 
					5fcf08a415 | ||
| 
						 | 
					3c06568ed5 | ||
| 
						 | 
					68e35e631a | ||
| 
						 | 
					ad8c76602b | ||
| 
						 | 
					b5c98ba99e | ||
| 
						 | 
					711f8dc6af | ||
| 
						 | 
					5b41fb98de | ||
| 
						 | 
					6da625dbdb | ||
| 
						 | 
					e862c47b8b | ||
| 
						 | 
					4a8fe56470 | ||
| 
						 | 
					7c3e61950d | ||
| 
						 | 
					61f89eef2e | ||
| 
						 | 
					06de587ed2 | ||
| 
						 | 
					49beb3ac08 | ||
| 
						 | 
					e1c944d723 | ||
| 
						 | 
					83442b9849 | ||
| 
						 | 
					edd6ffeb01 | ||
| 
						 | 
					5a8881000c | ||
| 
						 | 
					70839368c1 | ||
| 
						 | 
					9d8a2a1a7a | ||
| 
						 | 
					17174016ec | ||
| 
						 | 
					ed37174a2b | ||
| 
						 | 
					8660148960 | ||
| 
						 | 
					67ca2dd0f4 | ||
| 
						 | 
					882f984b26 | ||
| 
						 | 
					6175cbcd99 | ||
| 
						 | 
					476d76a533 | ||
| 
						 | 
					df68bb4896 | ||
| 
						 | 
					815e647c97 | ||
| 
						 | 
					ad70ffba59 | ||
| 
						 | 
					0e95015410 | ||
| 
						 | 
					b92dac72f3 | ||
| 
						 | 
					cdb9a6ff7e | ||
| 
						 | 
					a59148dfeb | ||
| 
						 | 
					07e46837d9 | ||
| 
						 | 
					fa21e262c7 | ||
| 
						 | 
					93934c7992 | ||
| 
						 | 
					73edd42774 | ||
| 
						 | 
					ab03ad54aa | ||
| 
						 | 
					2e571ac950 | ||
| 
						 | 
					6c15d65107 | ||
| 
						 | 
					e5af0597a6 | ||
| 
						 | 
					74117453b5 | ||
| 
						 | 
					5611b30022 | ||
| 
						 | 
					ede9dcd18f | ||
| 
						 | 
					d3b56a5d94 | ||
| 
						 | 
					f5d4334963 | ||
| 
						 | 
					5c769632e8 | ||
| 
						 | 
					373505f483 | ||
| 
						 | 
					a2cad40f91 | ||
| 
						 | 
					4328762076 | ||
| 
						 | 
					c2f6f07776 | ||
| 
						 | 
					5ab77c7452 | ||
| 
						 | 
					e5582694c0 | ||
| 
						 | 
					768136e493 | ||
| 
						 | 
					753cb3580e | ||
| 
						 | 
					60b050b82a | ||
| 
						 | 
					ad91a8cd5e | ||
| 
						 | 
					02f79fc94b | ||
| 
						 | 
					230a73fad2 | ||
| 
						 | 
					d94dd486fe | ||
| 
						 | 
					6ecc39b816 | ||
| 
						 | 
					9c240df9db | ||
| 
						 | 
					a918bf3a95 | ||
| 
						 | 
					9434ae267f | ||
| 
						 | 
					94187d215a | ||
| 
						 | 
					ef2f5d2978 | ||
| 
						 | 
					62671e0f56 | ||
| 
						 | 
					93869f77a0 | ||
| 
						 | 
					8282d135cc | ||
| 
						 | 
					9acc78c81d | ||
| 
						 | 
					3642469630 | ||
| 
						 | 
					34cd20339c | ||
| 
						 | 
					7548f44047 | ||
| 
						 | 
					7cf55ef695 | ||
| 
						 | 
					543250da13 | ||
| 
						 | 
					69e55d7316 | ||
| 
						 | 
					158411e918 | ||
| 
						 | 
					3f873002c4 | ||
| 
						 | 
					818f4e5973 | ||
| 
						 | 
					c8d6e512d2 | ||
| 
						 | 
					a2423b8499 | ||
| 
						 | 
					49acdac776 | ||
| 
						 | 
					7e1587faa2 | ||
| 
						 | 
					84a6ed8e80 | ||
| 
						 | 
					654420e351 | ||
| 
						 | 
					651915f31c | ||
| 
						 | 
					d9db1b84fe | ||
| 
						 | 
					bd03f071c6 | ||
| 
						 | 
					eb6ac68d5c | ||
| 
						 | 
					848e6ebd83 | ||
| 
						 | 
					f76524fc9f | ||
| 
						 | 
					b95532b68b | ||
| 
						 | 
					d002d4c06f | ||
| 
						 | 
					7c03cc622c | ||
| 
						 | 
					cebfd84416 | ||
| 
						 | 
					12995e280e | ||
| 
						 | 
					4ae6d44efc | ||
| 
						 | 
					01e1878900 | ||
| 
						 | 
					df9ad82336 | ||
| 
						 | 
					c183fd5e35 | ||
| 
						 | 
					820d07f309 | ||
| 
						 | 
					f4e3c04bbf | ||
| 
						 | 
					540d6e9dbb | ||
| 
						 | 
					79a3a2befd | ||
| 
						 | 
					08a0fd5420 | ||
| 
						 | 
					92d6bc6875 | ||
| 
						 | 
					fb5d20c4f8 | ||
| 
						 | 
					65e3122f52 | ||
| 
						 | 
					be874e3c70 | ||
| 
						 | 
					beae845281 | ||
| 
						 | 
					6f64dac262 | ||
| 
						 | 
					cd2d25cf87 | ||
| 
						 | 
					b8b2f37e7b | ||
| 
						 | 
					00152358de | ||
| 
						 | 
					a2784be4d6 | ||
| 
						 | 
					ad7a57103d | ||
| 
						 | 
					19b24b276d | ||
| 
						 | 
					23750357e2 | ||
| 
						 | 
					07284f380f | ||
| 
						 | 
					e60401278f | ||
| 
						 | 
					24c474a9ec | ||
| 
						 | 
					8fd3781ef5 | ||
| 
						 | 
					c85f2494a8 | ||
| 
						 | 
					6c2fa7a382 | ||
| 
						 | 
					45689fd879 | ||
| 
						 | 
					45a2cfb01b | ||
| 
						 | 
					c4bb6c900c | ||
| 
						 | 
					f7c042fc77 | ||
| 
						 | 
					b20dc9fe2b | ||
| 
						 | 
					a030e05993 | ||
| 
						 | 
					648b03f811 | ||
| 
						 | 
					e57e321d33 | ||
| 
						 | 
					b6e53c7b1b | ||
| 
						 | 
					1c3bfd949b | ||
| 
						 | 
					6401c9aaaa | ||
| 
						 | 
					c02adbb8e1 | ||
| 
						 | 
					88e64dbfae | ||
| 
						 | 
					afd48b9e08 | ||
| 
						 | 
					db0ab9a0b3 | ||
| 
						 | 
					556e4bd74d | ||
| 
						 | 
					d439c4f215 | ||
| 
						 | 
					a9f2e1482c | ||
| 
						 | 
					2c26fb0d76 | ||
| 
						 | 
					18dde97c8c | ||
| 
						 | 
					85bc6f5301 | ||
| 
						 | 
					8f364b9a95 | ||
| 
						 | 
					ee6c5632ac | ||
| 
						 | 
					cc81a0e8da | ||
| 
						 | 
					262652992d | ||
| 
						 | 
					eb63825dfd | ||
| 
						 | 
					c49017c6f1 | ||
| 
						 | 
					7d08bd3142 | ||
| 
						 | 
					f12c241dca | ||
| 
						 | 
					cedc9dd175 | ||
| 
						 | 
					669e708b70 | ||
| 
						 | 
					e76a483931 | ||
| 
						 | 
					c0437d2de8 | ||
| 
						 | 
					37a8043202 | ||
| 
						 | 
					f4c69d4045 | ||
| 
						 | 
					a3606d9e4d | ||
| 
						 | 
					805f1c0e39 | ||
| 
						 | 
					7430a8ca40 | ||
| 
						 | 
					1776e2edcc | ||
| 
						 | 
					baf9aaf26c | ||
| 
						 | 
					4864b07e13 | ||
| 
						 | 
					13c919773e | ||
| 
						 | 
					ed3a4fb8d4 | ||
| 
						 | 
					df3e826d0a | ||
| 
						 | 
					a9e7d489b8 | ||
| 
						 | 
					da6b549f8b | ||
| 
						 | 
					76e07a9089 | ||
| 
						 | 
					4a590d1497 | ||
| 
						 | 
					82e1508d6f | ||
| 
						 | 
					400f08db9d | ||
| 
						 | 
					e48b650caa | ||
| 
						 | 
					d9f595283a | ||
| 
						 | 
					85fd14f47f | ||
| 
						 | 
					b7adaafb3e | ||
| 
						 | 
					d0bba87cdd | ||
| 
						 | 
					2cc75d4bbd | ||
| 
						 | 
					24bd591faa | ||
| 
						 | 
					2e9ccd0623 | ||
| 
						 | 
					7b49c82210 | ||
| 
						 | 
					d3284f1604 | ||
| 
						 | 
					3279697128 | ||
| 
						 | 
					60cfab995f | ||
| 
						 | 
					8ec18bdb2c | ||
| 
						 | 
					3c3cd65235 | ||
| 
						 | 
					7ac75de19d | ||
| 
						 | 
					fae39e1ab4 | ||
| 
						 | 
					3732139fc3 | ||
| 
						 | 
					0a2737dc77 | ||
| 
						 | 
					481971928c | ||
| 
						 | 
					020197718f | ||
| 
						 | 
					a0c77c04a5 | ||
| 
						 | 
					620ee9719f | ||
| 
						 | 
					c0d02d9935 | ||
| 
						 | 
					01356d23e5 | ||
| 
						 | 
					8b73c2bcff | ||
| 
						 | 
					5a771dbe2f | ||
| 
						 | 
					9ba5b644cf | ||
| 
						 | 
					f76f0c3787 | ||
| 
						 | 
					01abd6a705 | ||
| 
						 | 
					44e2b5d945 | ||
| 
						 | 
					82bbe5d1a6 | ||
| 
						 | 
					a1d71d31e8 | ||
| 
						 | 
					766e0b685d | ||
| 
						 | 
					58f5e4702b | ||
| 
						 | 
					d9906756cf | ||
| 
						 | 
					9a45ebd98b | ||
| 
						 | 
					7f9ff9d0e7 | ||
| 
						 | 
					8c763fcf43 | ||
| 
						 | 
					6dd4456b11 | ||
| 
						 | 
					c30c47d291 | ||
| 
						 | 
					d8c9662302 | ||
| 
						 | 
					ec5e819b16 | ||
| 
						 | 
					55e50ad979 | ||
| 
						 | 
					99ecb166d3 | ||
| 
						 | 
					cdeae7e72f | ||
| 
						 | 
					fbf79755d7 | ||
| 
						 | 
					78bd21b7cf | ||
| 
						 | 
					88c7c29954 | ||
| 
						 | 
					d4dde89ea6 | ||
| 
						 | 
					774bf35fab | ||
| 
						 | 
					1a2db7fb11 | ||
| 
						 | 
					da3223ac92 | ||
| 
						 | 
					b0fed5a48d | ||
| 
						 | 
					43132dab85 | ||
| 
						 | 
					badd327360 | ||
| 
						 | 
					9a6bfc6614 | ||
| 
						 | 
					79914fb56b | ||
| 
						 | 
					75a792eb6f | ||
| 
						 | 
					23f112602c | ||
| 
						 | 
					639a3aa832 | ||
| 
						 | 
					79a8c5ceae | ||
| 
						 | 
					97a2f4449d | ||
| 
						 | 
					7f42d15175 | ||
| 
						 | 
					ef9c8e910c | ||
| 
						 | 
					a1b33da9ca | ||
| 
						 | 
					1741059cf6 | ||
| 
						 | 
					1f137735e1 | ||
| 
						 | 
					a186972f09 | ||
| 
						 | 
					751628401e | ||
| 
						 | 
					403b1802ec | ||
| 
						 | 
					9165cbf7f6 | ||
| 
						 | 
					bad405bea9 | ||
| 
						 | 
					4f9a95b011 | ||
| 
						 | 
					903e641457 | ||
| 
						 | 
					f34b9399cc | ||
| 
						 | 
					7d0d96f940 | ||
| 
						 | 
					27196a21ae | ||
| 
						 | 
					ea0381fa09 | ||
| 
						 | 
					3423589ba1 | ||
| 
						 | 
					1f9286d39e | ||
| 
						 | 
					93b8e66b5d | ||
| 
						 | 
					a1716de683 | ||
| 
						 | 
					ccf7916257 | ||
| 
						 | 
					d86adfa1b1 | ||
| 
						 | 
					648f3f978a | ||
| 
						 | 
					5e4b8bd67c | ||
| 
						 | 
					64ef690432 | ||
| 
						 | 
					41991b5982 | ||
| 
						 | 
					01da222d67 | ||
| 
						 | 
					518eee05c2 | ||
| 
						 | 
					1dbfa29a1e | ||
| 
						 | 
					6bac4741f6 | ||
| 
						 | 
					a0266dac6f | ||
| 
						 | 
					ce977a7809 | ||
| 
						 | 
					8644a83ed9 | ||
| 
						 | 
					7b45245b1d | ||
| 
						 | 
					f04f4e4a1a | ||
| 
						 | 
					b07f1b3bd3 | ||
| 
						 | 
					0e7486d7b4 | ||
| 
						 | 
					6c0afb87b9 | ||
| 
						 | 
					e5750b368e | ||
| 
						 | 
					ef76f923ad | ||
| 
						 | 
					2c04ae084c | ||
| 
						 | 
					91dc58d967 | ||
| 
						 | 
					0e2abe74d5 | ||
| 
						 | 
					fea444925e | ||
| 
						 | 
					0998429b07 | ||
| 
						 | 
					597eb1779c | ||
| 
						 | 
					9ae3a7dbff | ||
| 
						 | 
					3519e845a3 | ||
| 
						 | 
					29c049612a | ||
| 
						 | 
					ed48185732 | ||
| 
						 | 
					f431bbfca2 | ||
| 
						 | 
					8b29900be4 | ||
| 
						 | 
					6f8a4f8354 | ||
| 
						 | 
					def34f0e42 | ||
| 
						 | 
					e25a49f804 | ||
| 
						 | 
					b820351f64 | ||
| 
						 | 
					0eb009496e | ||
| 
						 | 
					2c2498b658 | ||
| 
						 | 
					a1d988fed5 | ||
| 
						 | 
					b0c50b7a59 | ||
| 
						 | 
					1a2b404076 | ||
| 
						 | 
					2d066c34fd | ||
| 
						 | 
					7a1ed64985 | ||
| 
						 | 
					1b449585f7 | ||
| 
						 | 
					032d41dbb8 | ||
| 
						 | 
					3a7569e3ea | ||
| 
						 | 
					d444930494 | ||
| 
						 | 
					6045a6bfb3 | ||
| 
						 | 
					f3f543b31e | ||
| 
						 | 
					0fea4262ea | ||
| 
						 | 
					4b7ec4a32a | ||
| 
						 | 
					a00eee1bbe | ||
| 
						 | 
					06a690a259 | ||
| 
						 | 
					14c9e9a9cc | ||
| 
						 | 
					931d49560a | ||
| 
						 | 
					3655827ef2 | ||
| 
						 | 
					12e0e1a16b | ||
| 
						 | 
					0d448b8221 | ||
| 
						 | 
					77f2a339e1 | ||
| 
						 | 
					7c485c6a8b | ||
| 
						 | 
					fc07e23ff8 | ||
| 
						 | 
					84a2fc382b | ||
| 
						 | 
					44e7585bf8 | ||
| 
						 | 
					a2c60a4911 | ||
| 
						 | 
					73ce9a5ecc | ||
| 
						 | 
					d385b9e708 | ||
| 
						 | 
					67147570e9 | ||
| 
						 | 
					df9ac58d05 | ||
| 
						 | 
					19a78f63f4 | ||
| 
						 | 
					e20610ab80 | ||
| 
						 | 
					f52a10b061 | ||
| 
						 | 
					7d382a2bfd | ||
| 
						 | 
					09bec1c4fe | ||
| 
						 | 
					ff28b0a005 | ||
| 
						 | 
					a249f8736a | ||
| 
						 | 
					f09adf0014 | ||
| 
						 | 
					04dc68f5f6 | ||
| 
						 | 
					5c25208fb5 | ||
| 
						 | 
					962dfad216 | ||
| 
						 | 
					14aa831169 | ||
| 
						 | 
					75d904ed01 | ||
| 
						 | 
					f81d5e4bd6 | ||
| 
						 | 
					2f65fdbc76 | ||
| 
						 | 
					2f4149c7d0 | ||
| 
						 | 
					fb4275648c | ||
| 
						 | 
					06a9d9fc30 | ||
| 
						 | 
					44ce01a70b | ||
| 
						 | 
					c2189b4ecd | ||
| 
						 | 
					c9b2cf6043 | ||
| 
						 | 
					16ec0f151a | ||
| 
						 | 
					c42f1ad4c7 | ||
| 
						 | 
					a3ec1af205 | ||
| 
						 | 
					2e580304f9 | ||
| 
						 | 
					5492e9028d | ||
| 
						 | 
					060c9ab679 | ||
| 
						 | 
					78f0325398 | ||
| 
						 | 
					1efe049959 | ||
| 
						 | 
					2393148908 | ||
| 
						 | 
					c7594b3ef0 | ||
| 
						 | 
					b210870f48 | ||
| 
						 | 
					5d6019a962 | ||
| 
						 | 
					eb5df1aa37 | ||
| 
						 | 
					546066d677 | ||
| 
						 | 
					3234596974 | ||
| 
						 | 
					5820d49cd4 | ||
| 
						 | 
					1ab66e5767 | ||
| 
						 | 
					aab2682f9a | ||
| 
						 | 
					55d332bcc8 | ||
| 
						 | 
					f89df6e70c | ||
| 
						 | 
					250d28e870 | ||
| 
						 | 
					19f65c8510 | ||
| 
						 | 
					f70b49882f | ||
| 
						 | 
					a7b092a305 | ||
| 
						 | 
					daa73a3f3c | ||
| 
						 | 
					0b51afe87a | ||
| 
						 | 
					2b298766c9 | ||
| 
						 | 
					10664d723b | ||
| 
						 | 
					c012208a8f | ||
| 
						 | 
					0953896d2d | ||
| 
						 | 
					cf9e89d0ae | ||
| 
						 | 
					48dd01b0bb | ||
| 
						 | 
					7247efe055 | ||
| 
						 | 
					8def3758e4 | ||
| 
						 | 
					1851ab6f5f | ||
| 
						 | 
					289b052338 | ||
| 
						 | 
					26147f5ae0 | ||
| 
						 | 
					ae01f1071a | ||
| 
						 | 
					dcdf5dcd09 | ||
| 
						 | 
					c59a6d0f51 | ||
| 
						 | 
					2cd936318d | ||
| 
						 | 
					2f38857681 | ||
| 
						 | 
					39505ae1ff | ||
| 
						 | 
					44ee0633f2 | ||
| 
						 | 
					b52d2768b0 | ||
| 
						 | 
					cf24b870b1 | ||
| 
						 | 
					69cffce7dc | ||
| 
						 | 
					a14979375b | ||
| 
						 | 
					40ef4a16b1 | 
							
								
								
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
*.pyc
 | 
			
		||||
*.py[co]
 | 
			
		||||
build/
 | 
			
		||||
dist/
 | 
			
		||||
MANIFEST
 | 
			
		||||
@@ -6,4 +6,9 @@ docs/_build/
 | 
			
		||||
*.swp
 | 
			
		||||
.tox/
 | 
			
		||||
.coverage
 | 
			
		||||
sleekxmpp.egg-info/
 | 
			
		||||
slixmpp.egg-info/
 | 
			
		||||
.ropeproject/
 | 
			
		||||
4913
 | 
			
		||||
*~
 | 
			
		||||
.baboon/
 | 
			
		||||
.DS_STORE
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								INSTALL
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								INSTALL
									
									
									
									
									
								
							@@ -1,5 +1,6 @@
 | 
			
		||||
Pre-requisites:
 | 
			
		||||
- Python 3.1 or 2.6
 | 
			
		||||
- Python 3.4
 | 
			
		||||
- Cython 0.22 and libidn, optionally (making JID faster by compiling the stringprep module)
 | 
			
		||||
 | 
			
		||||
Install:
 | 
			
		||||
> python3 setup.py install
 | 
			
		||||
@@ -9,4 +10,4 @@ Root install:
 | 
			
		||||
 | 
			
		||||
To test:
 | 
			
		||||
> cd examples
 | 
			
		||||
> python echo_client.py -v -j [USER@example.com] -p [PASSWORD]
 | 
			
		||||
> python3 echo_client.py -d -j [USER@example.com] -p [PASSWORD]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										31
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								LICENSE
									
									
									
									
									
								
							@@ -69,8 +69,8 @@ modification, are permitted provided that the following conditions are met:
 | 
			
		||||
    * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
      notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
      documentation and/or other materials provided with the distribution.
 | 
			
		||||
    * Neither the name of Red Innovation nor the names of its contributors 
 | 
			
		||||
      may be used to endorse or promote products derived from this software 
 | 
			
		||||
    * Neither the name of Red Innovation nor the names of its contributors
 | 
			
		||||
      may be used to endorse or promote products derived from this software
 | 
			
		||||
      without specific prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY RED INNOVATION ``AS IS'' AND ANY
 | 
			
		||||
@@ -119,7 +119,7 @@ SUELTA – A PURE-PYTHON SASL CLIENT LIBRARY
 | 
			
		||||
 | 
			
		||||
This software is subject to "The MIT License"
 | 
			
		||||
 | 
			
		||||
Copyright 2007-2010 David Alan Cridland
 | 
			
		||||
Copyright 2004-2013 David Alan Cridland
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
@@ -167,3 +167,28 @@ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 | 
			
		||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 | 
			
		||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
socksipy: A Python SOCKS client module.
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
Copyright 2006 Dan-Haim. All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without modification,
 | 
			
		||||
are permitted provided that the following conditions are met:
 | 
			
		||||
1. Redistributions of source code must retain the above copyright notice, this
 | 
			
		||||
   list of conditions and the following disclaimer.
 | 
			
		||||
2. Redistributions in binary form must reproduce the above copyright notice,
 | 
			
		||||
   this list of conditions and the following disclaimer in the documentation
 | 
			
		||||
   and/or other materials provided with the distribution.
 | 
			
		||||
3. Neither the name of Dan Haim nor the names of his contributors may be used
 | 
			
		||||
   to endorse or promote products derived from this software without specific
 | 
			
		||||
   prior written permission.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY DAN HAIM "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 | 
			
		||||
EVENT SHALL DAN HAIM OR HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA
 | 
			
		||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
			
		||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMANGE.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										113
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								README.rst
									
									
									
									
									
								
							@@ -1,76 +1,12 @@
 | 
			
		||||
SleekXMPP
 | 
			
		||||
Slixmpp
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
SleekXMPP is an MIT licensed XMPP library for Python 2.6/3.1+,
 | 
			
		||||
and is featured in examples in
 | 
			
		||||
`XMPP: The Definitive Guide <http://oreilly.com/catalog/9780596521271>`_ 
 | 
			
		||||
by Kevin Smith, Remko Tronçon, and Peter Saint-Andre. If you've arrived
 | 
			
		||||
here from reading the Definitive Guide, please see the notes on updating
 | 
			
		||||
the examples to the latest version of SleekXMPP.
 | 
			
		||||
Slixmpp is an MIT licensed XMPP library for Python 3.4+. It is a fork of
 | 
			
		||||
SleekXMPP.
 | 
			
		||||
 | 
			
		||||
SleekXMPP's design goals and philosphy are:
 | 
			
		||||
 | 
			
		||||
**Low number of dependencies**
 | 
			
		||||
    Installing and using SleekXMPP should be as simple as possible, without
 | 
			
		||||
    having to deal with long dependency chains.
 | 
			
		||||
 | 
			
		||||
    As part of reducing the number of dependencies, some third party
 | 
			
		||||
    modules are included with SleekXMPP in the ``thirdparty`` directory.
 | 
			
		||||
    Imports from this module first try to import an existing installed
 | 
			
		||||
    version before loading the packaged version, when possible.
 | 
			
		||||
 | 
			
		||||
**Every XEP as a plugin**
 | 
			
		||||
    Following Python's "batteries included" approach, the goal is to
 | 
			
		||||
    provide support for all currently active XEPs (final and draft). Since
 | 
			
		||||
    adding XEP support is done through easy to create plugins, the hope is
 | 
			
		||||
    to also provide a solid base for implementing and creating experimental
 | 
			
		||||
    XEPs.
 | 
			
		||||
 | 
			
		||||
**Rewarding to work with**
 | 
			
		||||
    As much as possible, SleekXMPP should allow things to "just work" using
 | 
			
		||||
    sensible defaults and appropriate abstractions. XML can be ugly to work
 | 
			
		||||
    with, but it doesn't have to be that way.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Get the Code
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
Get the latest stable version from PyPI::
 | 
			
		||||
 | 
			
		||||
    pip install sleekxmpp
 | 
			
		||||
 | 
			
		||||
The latest source code for SleekXMPP may be found on `Github
 | 
			
		||||
<http://github.com/fritzy/SleekXMPP>`_. Releases can be found in the
 | 
			
		||||
``master`` branch, while the latest development version is in the
 | 
			
		||||
``develop`` branch.
 | 
			
		||||
 | 
			
		||||
**Latest Release**
 | 
			
		||||
    - `1.1.10 <http://github.com/fritzy/SleekXMPP/zipball/1.1.10>`_
 | 
			
		||||
 | 
			
		||||
**Develop Releases**
 | 
			
		||||
    - `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Installing DNSPython
 | 
			
		||||
---------------------
 | 
			
		||||
If you are using Python3 and wish to use dnspython, you will have to checkout and
 | 
			
		||||
install the ``python3`` branch::
 | 
			
		||||
 | 
			
		||||
    git clone http://github.com/rthalley/dnspython
 | 
			
		||||
    cd dnspython
 | 
			
		||||
    git checkout python3
 | 
			
		||||
    python3 setup.py install
 | 
			
		||||
 | 
			
		||||
Discussion
 | 
			
		||||
----------
 | 
			
		||||
A mailing list and XMPP chat room are available for discussing and getting
 | 
			
		||||
help with SleekXMPP.
 | 
			
		||||
 | 
			
		||||
**Mailing List**
 | 
			
		||||
    `SleekXMPP Discussion on Google Groups <http://groups.google.com/group/sleekxmpp-discussion>`_
 | 
			
		||||
 | 
			
		||||
**Chat**
 | 
			
		||||
    `sleek@conference.jabber.org <xmpp:sleek@conference.jabber.org?join>`_
 | 
			
		||||
Slixmpp's goals is to only rewrite the core of the library (the low level
 | 
			
		||||
socket handling, the timers, the events dispatching) in order to remove all
 | 
			
		||||
threads.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Documentation and Testing
 | 
			
		||||
@@ -83,22 +19,22 @@ be in ``docs/_build/html``::
 | 
			
		||||
    make html
 | 
			
		||||
    open _build/html/index.html
 | 
			
		||||
 | 
			
		||||
To run the test suite for SleekXMPP::
 | 
			
		||||
To run the test suite for Slixmpp::
 | 
			
		||||
 | 
			
		||||
    python testall.py
 | 
			
		||||
    python run_tests.py
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The SleekXMPP Boilerplate
 | 
			
		||||
The Slixmpp Boilerplate
 | 
			
		||||
-------------------------
 | 
			
		||||
Projects using SleekXMPP tend to follow a basic pattern for setting up client/component
 | 
			
		||||
connections and configuration. Here is the gist of the boilerplate needed for a SleekXMPP
 | 
			
		||||
Projects using Slixmpp tend to follow a basic pattern for setting up client/component
 | 
			
		||||
connections and configuration. Here is the gist of the boilerplate needed for a Slixmpp
 | 
			
		||||
based project. See the documetation or examples directory for more detailed archetypes for
 | 
			
		||||
SleekXMPP projects::
 | 
			
		||||
Slixmpp projects::
 | 
			
		||||
 | 
			
		||||
    import logging
 | 
			
		||||
 | 
			
		||||
    from sleekxmpp import ClientXMPP
 | 
			
		||||
    from sleekxmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
    from slixmpp import ClientXMPP
 | 
			
		||||
    from slixmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    class EchoBot(ClientXMPP):
 | 
			
		||||
@@ -144,7 +80,7 @@ SleekXMPP projects::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if __name__ == '__main__':
 | 
			
		||||
        # Ideally use optparse or argparse to get JID, 
 | 
			
		||||
        # Ideally use optparse or argparse to get JID,
 | 
			
		||||
        # password, and log level.
 | 
			
		||||
 | 
			
		||||
        logging.basicConfig(level=logging.DEBUG,
 | 
			
		||||
@@ -152,21 +88,28 @@ SleekXMPP projects::
 | 
			
		||||
 | 
			
		||||
        xmpp = EchoBot('somejid@example.com', 'use_getpass')
 | 
			
		||||
        xmpp.connect()
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        xmpp.process(forever=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Credits
 | 
			
		||||
-------
 | 
			
		||||
Slixmpp Credits
 | 
			
		||||
---------------
 | 
			
		||||
 | 
			
		||||
**Maintainer of the slixmpp fork:** Florent Le Coz
 | 
			
		||||
    `louiz@louiz.org <xmpp:louiz@louiz.org?message>`_,
 | 
			
		||||
 | 
			
		||||
Credits (SleekXMPP)
 | 
			
		||||
-------------------
 | 
			
		||||
 | 
			
		||||
**Main Author:** Nathan Fritz
 | 
			
		||||
    `fritzy@netflint.net <xmpp:fritzy@netflint.net?message>`_, 
 | 
			
		||||
    `fritzy@netflint.net <xmpp:fritzy@netflint.net?message>`_,
 | 
			
		||||
    `@fritzy <http://twitter.com/fritzy>`_
 | 
			
		||||
 | 
			
		||||
    Nathan is also the author of XMPPHP and `Seesmic-AS3-XMPP
 | 
			
		||||
    <http://code.google.com/p/seesmic-as3-xmpp/>`_, and a former member of 
 | 
			
		||||
    <http://code.google.com/p/seesmic-as3-xmpp/>`_, and a former member of
 | 
			
		||||
    the XMPP Council.
 | 
			
		||||
 | 
			
		||||
**Co-Author:** Lance Stout
 | 
			
		||||
    `lancestout@gmail.com <xmpp:lancestout@gmail.com?message>`_, 
 | 
			
		||||
    `lancestout@gmail.com <xmpp:lancestout@gmail.com?message>`_,
 | 
			
		||||
    `@lancestout <http://twitter.com/lancestout>`_
 | 
			
		||||
 | 
			
		||||
**Contributors:**
 | 
			
		||||
 
 | 
			
		||||
@@ -72,17 +72,17 @@ qthelp:
 | 
			
		||||
	@echo
 | 
			
		||||
	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
 | 
			
		||||
	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
 | 
			
		||||
	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SleekXMPP.qhcp"
 | 
			
		||||
	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Slixmpp.qhcp"
 | 
			
		||||
	@echo "To view the help file:"
 | 
			
		||||
	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SleekXMPP.qhc"
 | 
			
		||||
	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Slixmpp.qhc"
 | 
			
		||||
 | 
			
		||||
devhelp:
 | 
			
		||||
	$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
 | 
			
		||||
	@echo
 | 
			
		||||
	@echo "Build finished."
 | 
			
		||||
	@echo "To view the help file:"
 | 
			
		||||
	@echo "# mkdir -p $$HOME/.local/share/devhelp/SleekXMPP"
 | 
			
		||||
	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SleekXMPP"
 | 
			
		||||
	@echo "# mkdir -p $$HOME/.local/share/devhelp/Slixmpp"
 | 
			
		||||
	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Slixmpp"
 | 
			
		||||
	@echo "# devhelp"
 | 
			
		||||
 | 
			
		||||
epub:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										68
									
								
								docs/_static/nature.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										68
									
								
								docs/_static/nature.css
									
									
									
									
										vendored
									
									
								
							@@ -8,11 +8,11 @@
 | 
			
		||||
 * :license: BSD, see LICENSE for details.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
@import url("basic.css");
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
/* -- page layout ----------------------------------------------------------- */
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
body {
 | 
			
		||||
    font-family: Arial, sans-serif;
 | 
			
		||||
    font-size: 100%;
 | 
			
		||||
@@ -34,18 +34,18 @@ div.bodywrapper {
 | 
			
		||||
hr {
 | 
			
		||||
    border: 1px solid #B1B4B6;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.document {
 | 
			
		||||
    background-color: #eee;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.body {
 | 
			
		||||
    background-color: #ffffff;
 | 
			
		||||
    color: #3E4349;
 | 
			
		||||
    padding: 0 30px 30px 30px;
 | 
			
		||||
    font-size: 0.9em;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.footer {
 | 
			
		||||
    color: #555;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
@@ -53,12 +53,12 @@ div.footer {
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    font-size: 75%;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.footer a {
 | 
			
		||||
    color: #444;
 | 
			
		||||
    text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.related {
 | 
			
		||||
    background-color: #6BA81E;
 | 
			
		||||
    line-height: 32px;
 | 
			
		||||
@@ -66,11 +66,11 @@ div.related {
 | 
			
		||||
    text-shadow: 0px 1px 0 #444;
 | 
			
		||||
    font-size: 0.9em;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.related a {
 | 
			
		||||
    color: #E2F3CC;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.sphinxsidebar {
 | 
			
		||||
    font-size: 0.75em;
 | 
			
		||||
    line-height: 1.5em;
 | 
			
		||||
@@ -79,7 +79,7 @@ div.sphinxsidebar {
 | 
			
		||||
div.sphinxsidebarwrapper{
 | 
			
		||||
    padding: 20px 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.sphinxsidebar h3,
 | 
			
		||||
div.sphinxsidebar h4 {
 | 
			
		||||
    font-family: Arial, sans-serif;
 | 
			
		||||
@@ -95,30 +95,30 @@ div.sphinxsidebar h4 {
 | 
			
		||||
div.sphinxsidebar h4{
 | 
			
		||||
    font-size: 1.1em;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.sphinxsidebar h3 a {
 | 
			
		||||
    color: #444;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
div.sphinxsidebar p {
 | 
			
		||||
    color: #888;
 | 
			
		||||
    padding: 5px 20px;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.sphinxsidebar p.topless {
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.sphinxsidebar ul {
 | 
			
		||||
    margin: 10px 20px;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    color: #000;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.sphinxsidebar a {
 | 
			
		||||
    color: #444;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.sphinxsidebar input {
 | 
			
		||||
    border: 1px solid #ccc;
 | 
			
		||||
    font-family: sans-serif;
 | 
			
		||||
@@ -128,19 +128,19 @@ div.sphinxsidebar input {
 | 
			
		||||
div.sphinxsidebar input[type=text]{
 | 
			
		||||
    margin-left: 20px;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
/* -- body styles ----------------------------------------------------------- */
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
a {
 | 
			
		||||
    color: #005B81;
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
a:hover {
 | 
			
		||||
    color: #E32E00;
 | 
			
		||||
    text-decoration: underline;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.body h1,
 | 
			
		||||
div.body h2,
 | 
			
		||||
div.body h3,
 | 
			
		||||
@@ -155,30 +155,30 @@ div.body h6 {
 | 
			
		||||
    padding: 5px 0 5px 10px;
 | 
			
		||||
    text-shadow: 0px 1px 0 white
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
 | 
			
		||||
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
 | 
			
		||||
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
 | 
			
		||||
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
 | 
			
		||||
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
 | 
			
		||||
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
a.headerlink {
 | 
			
		||||
    color: #c60f0f;
 | 
			
		||||
    font-size: 0.8em;
 | 
			
		||||
    padding: 0 4px 0 4px;
 | 
			
		||||
    text-decoration: none;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
a.headerlink:hover {
 | 
			
		||||
    background-color: #c60f0f;
 | 
			
		||||
    color: white;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.body p, div.body dd, div.body li {
 | 
			
		||||
    line-height: 1.5em;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.admonition p.admonition-title + p {
 | 
			
		||||
    display: inline;
 | 
			
		||||
}
 | 
			
		||||
@@ -191,29 +191,29 @@ div.note {
 | 
			
		||||
    background-color: #eee;
 | 
			
		||||
    border: 1px solid #ccc;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.seealso {
 | 
			
		||||
    background-color: #ffc;
 | 
			
		||||
    border: 1px solid #ff6;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.topic {
 | 
			
		||||
    background-color: #eee;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
div.warning {
 | 
			
		||||
    background-color: #ffe4e4;
 | 
			
		||||
    border: 1px solid #f66;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
p.admonition-title {
 | 
			
		||||
    display: inline;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
p.admonition-title:after {
 | 
			
		||||
    content: ":";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
pre {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
    background-color: White;
 | 
			
		||||
@@ -225,7 +225,7 @@ pre {
 | 
			
		||||
    -webkit-box-shadow: 1px 1px 1px #d8d8d8;
 | 
			
		||||
    -moz-box-shadow: 1px 1px 1px #d8d8d8;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
tt {
 | 
			
		||||
    background-color: #ecf0f3;
 | 
			
		||||
    color: #222;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								docs/_static/sphinxdoc.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								docs/_static/sphinxdoc.css
									
									
									
									
										vendored
									
									
								
							@@ -134,7 +134,7 @@ div.footer a {
 | 
			
		||||
 | 
			
		||||
/* -- body styles ----------------------------------------------------------- */
 | 
			
		||||
 | 
			
		||||
p {    
 | 
			
		||||
p {
 | 
			
		||||
    margin: 0.8em 0 0.5em 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
BaseXMPP
 | 
			
		||||
========
 | 
			
		||||
 | 
			
		||||
.. module:: sleekxmpp.basexmpp
 | 
			
		||||
.. module:: slixmpp.basexmpp
 | 
			
		||||
 | 
			
		||||
.. autoclass:: BaseXMPP
 | 
			
		||||
    :members:
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
ClientXMPP
 | 
			
		||||
==========
 | 
			
		||||
 | 
			
		||||
.. module:: sleekxmpp.clientxmpp
 | 
			
		||||
.. module:: slixmpp.clientxmpp
 | 
			
		||||
 | 
			
		||||
.. autoclass:: ClientXMPP
 | 
			
		||||
    :members:
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
ComponentXMPP
 | 
			
		||||
=============
 | 
			
		||||
 | 
			
		||||
.. module:: sleekxmpp.componentxmpp
 | 
			
		||||
.. module:: slixmpp.componentxmpp
 | 
			
		||||
 | 
			
		||||
.. autoclass:: ComponentXMPP
 | 
			
		||||
    :members:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
Exceptions
 | 
			
		||||
==========
 | 
			
		||||
 | 
			
		||||
.. module:: sleekxmpp.exceptions
 | 
			
		||||
.. module:: slixmpp.exceptions
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
.. autoexception:: XMPPError
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								docs/api/stanza/iq.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docs/api/stanza/iq.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
IQ Stanza
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
.. module:: slixmpp.stanza
 | 
			
		||||
 | 
			
		||||
.. autoclass:: Iq
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								docs/api/stanza/message.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								docs/api/stanza/message.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
Message Stanza
 | 
			
		||||
==============
 | 
			
		||||
 | 
			
		||||
.. module:: slixmpp.stanza
 | 
			
		||||
 | 
			
		||||
.. autoclass:: Message
 | 
			
		||||
    :members:
 | 
			
		||||
							
								
								
									
										8
									
								
								docs/api/stanza/presence.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docs/api/stanza/presence.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
Presence Stanza
 | 
			
		||||
===============
 | 
			
		||||
 | 
			
		||||
.. module:: slixmpp.stanza
 | 
			
		||||
 | 
			
		||||
.. autoclass:: Presence
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								docs/api/stanza/rootstanza.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								docs/api/stanza/rootstanza.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
Root Stanza
 | 
			
		||||
===========
 | 
			
		||||
 | 
			
		||||
.. module:: slixmpp.stanza.rootstanza
 | 
			
		||||
 | 
			
		||||
.. autoclass:: RootStanza
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
@@ -1,12 +0,0 @@
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.filesocket
 | 
			
		||||
 | 
			
		||||
.. _filesocket:
 | 
			
		||||
 | 
			
		||||
Python 2.6 File Socket Shims
 | 
			
		||||
============================
 | 
			
		||||
 | 
			
		||||
.. autoclass:: FileSocket
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
.. autoclass:: Socket26
 | 
			
		||||
    :members:
 | 
			
		||||
@@ -3,22 +3,26 @@ Stanza Handlers
 | 
			
		||||
 | 
			
		||||
The Basic Handler
 | 
			
		||||
-----------------
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.handler.base
 | 
			
		||||
.. module:: slixmpp.xmlstream.handler.base
 | 
			
		||||
 | 
			
		||||
.. autoclass:: BaseHandler
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
Callback
 | 
			
		||||
--------
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.handler.callback
 | 
			
		||||
.. module:: slixmpp.xmlstream.handler
 | 
			
		||||
 | 
			
		||||
.. autoclass:: Callback
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
CoroutineCallback
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
.. autoclass:: CoroutineCallback
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
Waiter
 | 
			
		||||
------
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.handler.waiter
 | 
			
		||||
 | 
			
		||||
.. autoclass:: Waiter
 | 
			
		||||
    :members:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
Jabber IDs (JID)
 | 
			
		||||
=================
 | 
			
		||||
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.jid
 | 
			
		||||
.. module:: slixmpp.jid
 | 
			
		||||
 | 
			
		||||
.. autoclass:: JID
 | 
			
		||||
    :members:
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ Stanza Matchers
 | 
			
		||||
 | 
			
		||||
The Basic Matcher
 | 
			
		||||
-----------------
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.matcher.base
 | 
			
		||||
.. module:: slixmpp.xmlstream.matcher.base
 | 
			
		||||
 | 
			
		||||
.. autoclass:: MatcherBase
 | 
			
		||||
    :members:
 | 
			
		||||
@@ -11,7 +11,7 @@ The Basic Matcher
 | 
			
		||||
 | 
			
		||||
ID Matching
 | 
			
		||||
-----------
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.matcher.id
 | 
			
		||||
.. module:: slixmpp.xmlstream.matcher.id
 | 
			
		||||
 | 
			
		||||
.. autoclass:: MatcherId
 | 
			
		||||
    :members:
 | 
			
		||||
@@ -19,7 +19,7 @@ ID Matching
 | 
			
		||||
 | 
			
		||||
Stanza Path Matching
 | 
			
		||||
--------------------
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.matcher.stanzapath
 | 
			
		||||
.. module:: slixmpp.xmlstream.matcher.stanzapath
 | 
			
		||||
 | 
			
		||||
.. autoclass:: StanzaPath
 | 
			
		||||
    :members:
 | 
			
		||||
@@ -27,7 +27,7 @@ Stanza Path Matching
 | 
			
		||||
 | 
			
		||||
XPath
 | 
			
		||||
-----
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.matcher.xpath
 | 
			
		||||
.. module:: slixmpp.xmlstream.matcher.xpath
 | 
			
		||||
 | 
			
		||||
.. autoclass:: MatchXPath
 | 
			
		||||
    :members:
 | 
			
		||||
@@ -35,7 +35,7 @@ XPath
 | 
			
		||||
 | 
			
		||||
XMLMask
 | 
			
		||||
-------
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.matcher.xmlmask
 | 
			
		||||
.. module:: slixmpp.xmlstream.matcher.xmlmask
 | 
			
		||||
 | 
			
		||||
.. autoclass:: MatchXMLMask
 | 
			
		||||
    :members:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
=========
 | 
			
		||||
Scheduler
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.scheduler
 | 
			
		||||
 | 
			
		||||
.. autoclass:: Task
 | 
			
		||||
    :members:
 | 
			
		||||
 | 
			
		||||
.. autoclass:: Scheduler
 | 
			
		||||
    :members:
 | 
			
		||||
@@ -4,9 +4,9 @@
 | 
			
		||||
Stanza Objects
 | 
			
		||||
==============
 | 
			
		||||
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.stanzabase
 | 
			
		||||
.. module:: slixmpp.xmlstream.stanzabase
 | 
			
		||||
 | 
			
		||||
The :mod:`~sleekmxpp.xmlstream.stanzabase` module provides a wrapper for the
 | 
			
		||||
The :mod:`~slixmpp.xmlstream.stanzabase` module provides a wrapper for the
 | 
			
		||||
standard :mod:`~xml.etree.ElementTree` module that makes working with XML
 | 
			
		||||
less painful. Instead of having to manually move up and down an element
 | 
			
		||||
tree and insert subelements and attributes, you can interact with an object
 | 
			
		||||
@@ -52,17 +52,17 @@ elements of the original XML chunk.
 | 
			
		||||
.. seealso::
 | 
			
		||||
    :ref:`create-stanza-interfaces`.
 | 
			
		||||
 | 
			
		||||
Because the :mod:`~sleekxmpp.xmlstream.stanzabase` module was developed
 | 
			
		||||
Because the :mod:`~slixmpp.xmlstream.stanzabase` module was developed
 | 
			
		||||
as part of an `XMPP <http://xmpp.org>`_ library, these chunks of XML are
 | 
			
		||||
referred to as :term:`stanzas <stanza>`, and in SleekXMPP we refer to a
 | 
			
		||||
referred to as :term:`stanzas <stanza>`, and in Slixmpp we refer to a
 | 
			
		||||
subclass of :class:`ElementBase` which defines the interfaces needed for
 | 
			
		||||
interacting with a given :term:`stanza` a :term:`stanza object`.
 | 
			
		||||
 | 
			
		||||
To make dealing with more complicated and nested :term:`stanzas <stanza>`
 | 
			
		||||
or XML chunks easier, :term:`stanza objects <stanza object>` can be
 | 
			
		||||
composed in two ways: as iterable child objects or as plugins. Iterable
 | 
			
		||||
child stanzas, or :term:`substanzas`, are accessible through a special
 | 
			
		||||
``'substanzas'`` interface. This option is useful for stanzas which
 | 
			
		||||
child stanzas, or :term:`substanzas <substanza>`, are accessible through a
 | 
			
		||||
special ``'substanzas'`` interface. This option is useful for stanzas which
 | 
			
		||||
may contain more than one of the same kind of element. When there is
 | 
			
		||||
only one child element, the plugin method is more useful. For plugins,
 | 
			
		||||
a parent stanza object delegates one of its XML child elements to the
 | 
			
		||||
@@ -72,7 +72,7 @@ plugin stanza object. Here is an example:
 | 
			
		||||
 | 
			
		||||
    <iq type="result">
 | 
			
		||||
      <query xmlns="http://jabber.org/protocol/disco#info">
 | 
			
		||||
        <identity category="client" type="bot" name="SleekXMPP Bot" />
 | 
			
		||||
        <identity category="client" type="bot" name="Slixmpp Bot" />
 | 
			
		||||
      </query>
 | 
			
		||||
    </iq>
 | 
			
		||||
 | 
			
		||||
@@ -84,13 +84,13 @@ we can access the plugin as so::
 | 
			
		||||
 | 
			
		||||
    >>> iq['disco_info']
 | 
			
		||||
    '<query xmlns="http://jabber.org/protocol/disco#info">
 | 
			
		||||
      <identity category="client" type="bot" name="SleekXMPP Bot" />
 | 
			
		||||
      <identity category="client" type="bot" name="Slixmpp Bot" />
 | 
			
		||||
    </query>'
 | 
			
		||||
 | 
			
		||||
We can then drill down through the plugin object's interfaces as desired::
 | 
			
		||||
 | 
			
		||||
    >>> iq['disco_info']['identities']
 | 
			
		||||
    [('client', 'bot', 'SleekXMPP Bot')]
 | 
			
		||||
    [('client', 'bot', 'Slixmpp Bot')]
 | 
			
		||||
 | 
			
		||||
Plugins may also add new interfaces to the parent stanza object as if they
 | 
			
		||||
had been defined by the parent directly, and can also override the behaviour
 | 
			
		||||
@@ -101,7 +101,7 @@ of an interface defined by the parent.
 | 
			
		||||
    - :ref:`create-stanza-plugins`
 | 
			
		||||
    - :ref:`create-extension-plugins`
 | 
			
		||||
    - :ref:`override-parent-interfaces`
 | 
			
		||||
     
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Registering Stanza Plugins
 | 
			
		||||
--------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,18 @@
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.tostring
 | 
			
		||||
.. module:: slixmpp.xmlstream.tostring
 | 
			
		||||
 | 
			
		||||
.. _tostring:
 | 
			
		||||
 | 
			
		||||
XML Serialization
 | 
			
		||||
=================
 | 
			
		||||
 | 
			
		||||
Since the XML layer of SleekXMPP is based on :mod:`~xml.etree.ElementTree`,
 | 
			
		||||
Since the XML layer of Slixmpp is based on :mod:`~xml.etree.ElementTree`,
 | 
			
		||||
why not just use the built-in :func:`~xml.etree.ElementTree.tostring`
 | 
			
		||||
method? The answer is that using that method produces ugly results when
 | 
			
		||||
using namespaces. The :func:`tostring()` method used here intelligently
 | 
			
		||||
hides namespaces when able and does not introduce excessive namespace
 | 
			
		||||
prefixes::
 | 
			
		||||
 | 
			
		||||
    >>> from sleekxmpp.xmlstream.tostring import tostring
 | 
			
		||||
    >>> from slixmpp.xmlstream.tostring import tostring
 | 
			
		||||
    >>> from xml.etree import cElementTree as ET
 | 
			
		||||
    >>> xml = ET.fromstring('<foo xmlns="bar"><baz /></foo>')
 | 
			
		||||
    >>> ET.tostring(xml)
 | 
			
		||||
@@ -25,10 +25,10 @@ produce unexpected results depending on how the :func:`tostring()` method
 | 
			
		||||
is invoked. For example, when sending XML on the wire, the main XMPP
 | 
			
		||||
stanzas with their namespace of ``jabber:client`` will not include the
 | 
			
		||||
namespace because that is already declared by the stream header. But, if
 | 
			
		||||
you create a :class:`~sleekxmpp.stanza.message.Message` instance and dump
 | 
			
		||||
you create a :class:`~slixmpp.stanza.message.Message` instance and dump
 | 
			
		||||
it to the terminal, the ``jabber:client`` namespace will appear.
 | 
			
		||||
 | 
			
		||||
.. autofunction:: tostring
 | 
			
		||||
.. autofunction:: slixmpp.xmlstream.tostring
 | 
			
		||||
 | 
			
		||||
Escaping Special Characters
 | 
			
		||||
---------------------------
 | 
			
		||||
@@ -43,4 +43,5 @@ In the future, the use of CDATA sections may be allowed to reduce the
 | 
			
		||||
size of escaped text or for when other XMPP processing agents do not
 | 
			
		||||
undertand these entities.
 | 
			
		||||
 | 
			
		||||
.. autofunction:: xml_escape
 | 
			
		||||
..
 | 
			
		||||
    autofunction:: xml_escape
 | 
			
		||||
 
 | 
			
		||||
@@ -2,9 +2,7 @@
 | 
			
		||||
XML Stream
 | 
			
		||||
==========
 | 
			
		||||
 | 
			
		||||
.. module:: sleekxmpp.xmlstream.xmlstream
 | 
			
		||||
 | 
			
		||||
.. autoexception:: RestartStream
 | 
			
		||||
.. module:: slixmpp.xmlstream.xmlstream
 | 
			
		||||
 | 
			
		||||
.. autoclass:: XMLStream
 | 
			
		||||
    :members:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
.. index:: XMLStream, BaseXMPP, ClientXMPP, ComponentXMPP
 | 
			
		||||
 | 
			
		||||
SleekXMPP Architecture
 | 
			
		||||
Slixmpp Architecture
 | 
			
		||||
======================
 | 
			
		||||
 | 
			
		||||
The core of SleekXMPP is contained in four classes: ``XMLStream``,
 | 
			
		||||
The core of Slixmpp is contained in four classes: ``XMLStream``,
 | 
			
		||||
``BaseXMPP``, ``ClientXMPP``, and ``ComponentXMPP``. Along side this
 | 
			
		||||
stack is a library for working with XML objects that eliminates most
 | 
			
		||||
of the tedium of creating/manipulating XML.
 | 
			
		||||
@@ -17,28 +17,27 @@ of the tedium of creating/manipulating XML.
 | 
			
		||||
 | 
			
		||||
The Foundation: XMLStream
 | 
			
		||||
-------------------------
 | 
			
		||||
:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` is a mostly XMPP-agnostic
 | 
			
		||||
:class:`~slixmpp.xmlstream.xmlstream.XMLStream` is a mostly XMPP-agnostic
 | 
			
		||||
class whose purpose is to read and write from a bi-directional XML stream.
 | 
			
		||||
It also allows for callback functions to execute when XML matching given
 | 
			
		||||
patterns is received; these callbacks are also referred to as :term:`stream
 | 
			
		||||
handlers <stream handler>`. The class also provides a basic eventing system
 | 
			
		||||
which can be triggered either manually or on a timed schedule.
 | 
			
		||||
 | 
			
		||||
The Main Threads
 | 
			
		||||
~~~~~~~~~~~~~~~~
 | 
			
		||||
:class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` instances run using at
 | 
			
		||||
least three background threads: the send thread, the read thread, and the
 | 
			
		||||
scheduler thread. The send thread is in charge of monitoring the send queue
 | 
			
		||||
and writing text to the outgoing XML stream. The read thread pulls text off
 | 
			
		||||
of the incoming XML stream and stores the results in an event queue. The
 | 
			
		||||
scheduler thread is used to emit events after a given period of time.
 | 
			
		||||
The event loop
 | 
			
		||||
~~~~~~~~~~~~~~
 | 
			
		||||
:class:`~slixmpp.xmlstream.xmlstream.XMLStream` instances inherit the
 | 
			
		||||
:class:`asyncio.BaseProtocol` class, and therefore do not have to handle
 | 
			
		||||
reads and writes directly, but receive data through
 | 
			
		||||
:meth:`~slixmpp.xmlstream.xmlstream.XMLStream.data_received` and write
 | 
			
		||||
data in the socket transport.
 | 
			
		||||
 | 
			
		||||
Additionally, the main event processing loop may be executed in its
 | 
			
		||||
own thread if SleekXMPP is being used in the background for another
 | 
			
		||||
application.
 | 
			
		||||
Upon receiving data, :term:`stream handlers <stream handler>` are run
 | 
			
		||||
immediately, except if they are coroutines, in which case they are
 | 
			
		||||
scheduled using :meth:`asyncio.async`.
 | 
			
		||||
 | 
			
		||||
Short-lived threads may also be spawned as requested for threaded
 | 
			
		||||
:term:`event handlers <event handler>`.
 | 
			
		||||
:term:`Event handlers <event handler>` (which are called inside
 | 
			
		||||
:term:`stream handlers <stream handler>`) work the same way.
 | 
			
		||||
 | 
			
		||||
How XML Text is Turned into Action
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
@@ -53,7 +52,7 @@ when this bit of XML is received (with an assumed namespace of
 | 
			
		||||
    </message>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
1. **Convert XML strings into objects.**
 | 
			
		||||
#. **Convert XML strings into objects.**
 | 
			
		||||
 | 
			
		||||
   Incoming text is parsed and converted into XML objects (using
 | 
			
		||||
   ElementTree) which are then wrapped into what are referred to as
 | 
			
		||||
@@ -61,95 +60,69 @@ when this bit of XML is received (with an assumed namespace of
 | 
			
		||||
   new object is determined using a map of namespaced element names to
 | 
			
		||||
   classes.
 | 
			
		||||
 | 
			
		||||
   Our incoming XML is thus turned into a :class:`~sleekxmpp.stanza.Message`
 | 
			
		||||
   Our incoming XML is thus turned into a :class:`~slixmpp.stanza.Message`
 | 
			
		||||
   :term:`stanza object` because the namespaced element name
 | 
			
		||||
   ``{jabber:client}message`` is associated with the class
 | 
			
		||||
   :class:`~sleekxmpp.stanza.Message`.
 | 
			
		||||
   :class:`~slixmpp.stanza.Message`.
 | 
			
		||||
 | 
			
		||||
2. **Match stanza objects to callbacks.**
 | 
			
		||||
#. **Match stanza objects to callbacks.**
 | 
			
		||||
 | 
			
		||||
   These objects are then compared against the stored patterns associated
 | 
			
		||||
   with the registered callback handlers. For each match, a copy of the
 | 
			
		||||
   :term:`stanza object` is paired with a reference to the handler and
 | 
			
		||||
   placed into the event queue.
 | 
			
		||||
   with the registered callback handlers.
 | 
			
		||||
 | 
			
		||||
   Our :class:`~sleekxmpp.stanza.Message` object is thus paired with the message stanza handler
 | 
			
		||||
   :meth:`BaseXMPP._handle_message` to create the tuple::
 | 
			
		||||
   Each handler matching our :term:`stanza object` is then added to a list.
 | 
			
		||||
 | 
			
		||||
       ('stanza', stanza_obj, handler)
 | 
			
		||||
#. **Processing callbacks**
 | 
			
		||||
 | 
			
		||||
3. **Process the event queue.**
 | 
			
		||||
   Every handler in the list is then called with the :term:`stanza object`
 | 
			
		||||
   as a parameter; if the handler is a
 | 
			
		||||
   :class:`~slixmpp.xmlstream.handler.CoroutineCallback`
 | 
			
		||||
   then it will be scheduled in the event loop using :meth:`asyncio.async`
 | 
			
		||||
   instead of run.
 | 
			
		||||
 | 
			
		||||
   The event queue is the heart of SleekXMPP. Nearly every action that
 | 
			
		||||
   takes place is first inserted into this queue, whether that be received
 | 
			
		||||
   stanzas, custom events, or scheduled events.
 | 
			
		||||
 | 
			
		||||
   When the stanza is pulled out of the event queue with an associated
 | 
			
		||||
   callback, the callback function is executed with the stanza as its only
 | 
			
		||||
   parameter.
 | 
			
		||||
 | 
			
		||||
   .. warning:: 
 | 
			
		||||
       The callback, aka :term:`stream handler`, is executed in the main event
 | 
			
		||||
       processing thread. If the handler blocks, event processing will also
 | 
			
		||||
       block.
 | 
			
		||||
 | 
			
		||||
4. **Raise Custom Events**
 | 
			
		||||
#. **Raise Custom Events**
 | 
			
		||||
 | 
			
		||||
   Since a :term:`stream handler` shouldn't block, if extensive processing
 | 
			
		||||
   for a stanza is required (such as needing to send and receive an
 | 
			
		||||
   :class:`~sleekxmpp.stanza.Iq` stanza), then custom events must be used.
 | 
			
		||||
   :class:`~slixmpp.stanza.Iq` stanza), then custom events must be used.
 | 
			
		||||
   These events are not explicitly tied to the incoming XML stream and may
 | 
			
		||||
   be raised at any time. Importantly, these events may be handled in their
 | 
			
		||||
   own thread.
 | 
			
		||||
   be raised at any time.
 | 
			
		||||
 | 
			
		||||
   When the event is raised, a copy of the stanza is created for each
 | 
			
		||||
   handler registered for the event. In contrast to :term:`stream handlers
 | 
			
		||||
   <stream handler>`, these functions are referred to as :term:`event
 | 
			
		||||
   handlers <event handler>`. Each stanza/handler pair is then put into the
 | 
			
		||||
   event queue.
 | 
			
		||||
 | 
			
		||||
   .. note::
 | 
			
		||||
       It is possible to skip the event queue and process an event immediately
 | 
			
		||||
       by using ``direct=True`` when raising the event.
 | 
			
		||||
   In contrast to :term:`stream handlers <stream handler>`, these functions
 | 
			
		||||
   are referred to as :term:`event handlers <event handler>`.
 | 
			
		||||
 | 
			
		||||
   The code for :meth:`BaseXMPP._handle_message` follows this pattern, and
 | 
			
		||||
   raises a ``'message'`` event::
 | 
			
		||||
   raises a ``'message'`` event
 | 
			
		||||
 | 
			
		||||
       self.event('message', msg)
 | 
			
		||||
   .. code-block:: python
 | 
			
		||||
 | 
			
		||||
   The event call then places the message object back into the event queue
 | 
			
		||||
   paired with an :term:`event handler`::
 | 
			
		||||
        self.event('message', msg)
 | 
			
		||||
 | 
			
		||||
       ('event', 'message', msg_copy1, custom_event_handler_1)
 | 
			
		||||
       ('event', 'message', msg_copy2, custom_evetn_handler_2) 
 | 
			
		||||
#. **Process Custom Events**
 | 
			
		||||
 | 
			
		||||
5. **Process Custom Events**
 | 
			
		||||
 | 
			
		||||
   The stanza and :term:`event handler` are then pulled from the event
 | 
			
		||||
   queue, and the handler is executed, passing the stanza as its only
 | 
			
		||||
   argument. If the handler was registered as threaded, then a new thread
 | 
			
		||||
   will be spawned for it.
 | 
			
		||||
   The :term:`event handlers <event handler>` are then executed, passing
 | 
			
		||||
   the stanza as the only argument.
 | 
			
		||||
 | 
			
		||||
   .. note::
 | 
			
		||||
       Events may be raised without needing :term:`stanza objects <stanza object>`. 
 | 
			
		||||
       For example, you could use ``self.event('custom', {'a': 'b'})``. 
 | 
			
		||||
       You don't even need any arguments: ``self.event('no_parameters')``. 
 | 
			
		||||
       Events may be raised without needing :term:`stanza objects <stanza object>`.
 | 
			
		||||
       For example, you could use ``self.event('custom', {'a': 'b'})``.
 | 
			
		||||
       You don't even need any arguments: ``self.event('no_parameters')``.
 | 
			
		||||
       However, every event handler MUST accept at least one argument.
 | 
			
		||||
 | 
			
		||||
   Finally, after a long trek, our message is handed off to the user's
 | 
			
		||||
   custom handler in order to do awesome stuff::
 | 
			
		||||
 | 
			
		||||
       msg.reply()
 | 
			
		||||
       msg['body'] = "Hey! This is awesome!"
 | 
			
		||||
       msg.send()
 | 
			
		||||
       reply = msg.reply()
 | 
			
		||||
       reply['body'] = "Hey! This is awesome!"
 | 
			
		||||
       reply.send()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.. index:: BaseXMPP, XMLStream
 | 
			
		||||
 | 
			
		||||
Raising XMPP Awareness: BaseXMPP
 | 
			
		||||
--------------------------------
 | 
			
		||||
While :class:`~sleekxmpp.xmlstream.xmlstream.XMLStream` attempts to shy away
 | 
			
		||||
from anything too XMPP specific, :class:`~sleekxmpp.basexmpp.BaseXMPP`'s
 | 
			
		||||
While :class:`~slixmpp.xmlstream.xmlstream.XMLStream` attempts to shy away
 | 
			
		||||
from anything too XMPP specific, :class:`~slixmpp.basexmpp.BaseXMPP`'s
 | 
			
		||||
sole purpose is to provide foundational support for sending and receiving
 | 
			
		||||
XMPP stanzas. This support includes registering the basic message,
 | 
			
		||||
presence, and iq stanzas, methods for creating and sending stanzas, and
 | 
			
		||||
@@ -157,14 +130,14 @@ default handlers for incoming messages and keeping track of presence
 | 
			
		||||
notifications.
 | 
			
		||||
 | 
			
		||||
The plugin system for adding new XEP support is also maintained by
 | 
			
		||||
:class:`~sleekxmpp.basexmpp.BaseXMPP`.
 | 
			
		||||
:class:`~slixmpp.basexmpp.BaseXMPP`.
 | 
			
		||||
 | 
			
		||||
.. index:: ClientXMPP, BaseXMPP
 | 
			
		||||
 | 
			
		||||
ClientXMPP
 | 
			
		||||
----------
 | 
			
		||||
:class:`~sleekxmpp.clientxmpp.ClientXMPP` extends
 | 
			
		||||
:class:`~sleekxmpp.clientxmpp.BaseXMPP` with additional logic for connecting
 | 
			
		||||
:class:`~slixmpp.clientxmpp.ClientXMPP` extends
 | 
			
		||||
:class:`~slixmpp.clientxmpp.BaseXMPP` with additional logic for connecting
 | 
			
		||||
to an XMPP server by performing DNS lookups. It also adds support for stream
 | 
			
		||||
features such as STARTTLS and SASL.
 | 
			
		||||
 | 
			
		||||
@@ -172,6 +145,6 @@ features such as STARTTLS and SASL.
 | 
			
		||||
 | 
			
		||||
ComponentXMPP
 | 
			
		||||
-------------
 | 
			
		||||
:class:`~sleekxmpp.componentxmpp.ComponentXMPP` is only a thin layer on top of
 | 
			
		||||
:class:`~sleekxmpp.basexmpp.BaseXMPP` that implements the component handshake
 | 
			
		||||
:class:`~slixmpp.componentxmpp.ComponentXMPP` is only a thin layer on top of
 | 
			
		||||
:class:`~slixmpp.basexmpp.BaseXMPP` that implements the component handshake
 | 
			
		||||
protocol.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								docs/conf.py
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								docs/conf.py
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
# SleekXMPP documentation build configuration file, created by
 | 
			
		||||
# Slixmpp documentation build configuration file, created by
 | 
			
		||||
# sphinx-quickstart on Tue Aug  9 22:27:06 2011.
 | 
			
		||||
#
 | 
			
		||||
# This file is execfile()d with the current directory set to its containing dir.
 | 
			
		||||
@@ -40,7 +40,7 @@ source_suffix = '.rst'
 | 
			
		||||
master_doc = 'index'
 | 
			
		||||
 | 
			
		||||
# General information about the project.
 | 
			
		||||
project = u'SleekXMPP'
 | 
			
		||||
project = u'Slixmpp'
 | 
			
		||||
copyright = u'2011, Nathan Fritz, Lance Stout'
 | 
			
		||||
 | 
			
		||||
# The version info for the project you're documenting, acts as replacement for
 | 
			
		||||
@@ -105,7 +105,7 @@ html_theme = 'haiku'
 | 
			
		||||
 | 
			
		||||
# The name for this set of Sphinx documents.  If None, it defaults to
 | 
			
		||||
# "<project> v<release> documentation".
 | 
			
		||||
html_title = 'SleekXMPP'
 | 
			
		||||
html_title = 'slixmpp'
 | 
			
		||||
 | 
			
		||||
# A shorter title for the navigation bar.  Default is the same as html_title.
 | 
			
		||||
html_short_title = '%s Documentation' % release
 | 
			
		||||
@@ -168,7 +168,7 @@ html_additional_pages = {
 | 
			
		||||
#html_file_suffix = None
 | 
			
		||||
 | 
			
		||||
# Output file base name for HTML help builder.
 | 
			
		||||
htmlhelp_basename = 'SleekXMPPdoc'
 | 
			
		||||
htmlhelp_basename = 'Slixmppdoc'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# -- Options for LaTeX output --------------------------------------------------
 | 
			
		||||
@@ -182,7 +182,7 @@ htmlhelp_basename = 'SleekXMPPdoc'
 | 
			
		||||
# Grouping the document tree into LaTeX files. List of tuples
 | 
			
		||||
# (source start file, target name, title, author, documentclass [howto/manual]).
 | 
			
		||||
latex_documents = [
 | 
			
		||||
  ('index', 'SleekXMPP.tex', u'SleekXMPP Documentation',
 | 
			
		||||
  ('index', 'Slixmpp.tex', u'Slixmpp Documentation',
 | 
			
		||||
   u'Nathan Fritz, Lance Stout', 'manual'),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@@ -215,8 +215,8 @@ latex_documents = [
 | 
			
		||||
# One entry per manual page. List of tuples
 | 
			
		||||
# (source start file, name, description, authors, manual section).
 | 
			
		||||
man_pages = [
 | 
			
		||||
    ('index', 'sleekxmpp', u'SleekXMPP Documentation',
 | 
			
		||||
    ('index', 'slixmpp', u'Slixmpp Documentation',
 | 
			
		||||
     [u'Nathan Fritz, Lance Stout'], 1)
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
intersphinx_mapping = {'python': ('http://docs.python.org/3.2', 'python-objects.inv')}
 | 
			
		||||
intersphinx_mapping = {'python': ('http://docs.python.org/3.4', 'python-objects.inv')}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
.. _create-plugin:
 | 
			
		||||
 | 
			
		||||
Creating a SleekXMPP Plugin
 | 
			
		||||
Creating a Slixmpp Plugin
 | 
			
		||||
===========================
 | 
			
		||||
 | 
			
		||||
One of the goals of SleekXMPP is to provide support for every draft or final
 | 
			
		||||
XMPP extension (`XEP <http://xmpp.org/extensions/>`_). To do this, SleekXMPP has a
 | 
			
		||||
One of the goals of Slixmpp is to provide support for every draft or final
 | 
			
		||||
XMPP extension (`XEP <http://xmpp.org/extensions/>`_). To do this, Slixmpp has a
 | 
			
		||||
plugin mechanism for adding the functionalities required by each XEP. But even
 | 
			
		||||
though plugins were made to quickly implement and prototype the official XMPP
 | 
			
		||||
extensions, there is no reason you can't create your own plugin to implement
 | 
			
		||||
@@ -14,11 +14,11 @@ This guide will help walk you through the steps to
 | 
			
		||||
implement a rudimentary version of `XEP-0077 In-band
 | 
			
		||||
Registration <http://xmpp.org/extensions/xep-0077.html>`_. In-band registration
 | 
			
		||||
was implemented in example 14-6 (page 223) of `XMPP: The Definitive
 | 
			
		||||
Guide <http://oreilly.com/catalog/9780596521271>`_ because there was no SleekXMPP
 | 
			
		||||
Guide <http://oreilly.com/catalog/9780596521271>`_ because there was no Slixmpp
 | 
			
		||||
plugin for XEP-0077 at the time of writing. We will partially fix that issue
 | 
			
		||||
here by turning the example implementation from *XMPP: The Definitive Guide*
 | 
			
		||||
into a plugin. Again, note that this will not a complete implementation, and a
 | 
			
		||||
different, more robust, official plugin for XEP-0077 may be added to SleekXMPP
 | 
			
		||||
different, more robust, official plugin for XEP-0077 may be added to Slixmpp
 | 
			
		||||
in the future.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
@@ -29,10 +29,10 @@ in the future.
 | 
			
		||||
 | 
			
		||||
First Steps
 | 
			
		||||
-----------
 | 
			
		||||
Every plugin inherits from the class :mod:`base_plugin <sleekxmpp.plugins.base.base_plugin>`,
 | 
			
		||||
Every plugin inherits from the class :mod:`BasePlugin <slixmpp.plugins.base.BasePlugin`,
 | 
			
		||||
and must include a ``plugin_init`` method. While the
 | 
			
		||||
plugins distributed with SleekXMPP must be placed in the plugins directory
 | 
			
		||||
``sleekxmpp/plugins`` to be loaded, custom plugins may be loaded from any
 | 
			
		||||
plugins distributed with Slixmpp must be placed in the plugins directory
 | 
			
		||||
``slixmpp/plugins`` to be loaded, custom plugins may be loaded from any
 | 
			
		||||
module. To do so, use the following form when registering the plugin:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
@@ -40,9 +40,9 @@ module. To do so, use the following form when registering the plugin:
 | 
			
		||||
    self.register_plugin('myplugin', module=mod_containing_my_plugin)
 | 
			
		||||
 | 
			
		||||
The plugin name must be the same as the plugin's class name.
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
Now, we can open our favorite text editors and create ``xep_0077.py`` in
 | 
			
		||||
``SleekXMPP/sleekxmpp/plugins``. We want to do some basic house-keeping and
 | 
			
		||||
``Slixmpp/slixmpp/plugins``. We want to do some basic house-keeping and
 | 
			
		||||
declare the name and description of the XEP we are implementing. If you
 | 
			
		||||
are creating your own custom plugin, you don't need to include the ``xep``
 | 
			
		||||
attribute.
 | 
			
		||||
@@ -50,15 +50,15 @@ attribute.
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Creating a SleekXMPP Plugin
 | 
			
		||||
    Creating a Slixmpp Plugin
 | 
			
		||||
 | 
			
		||||
    This is a minimal implementation of XEP-0077 to serve
 | 
			
		||||
    as a tutorial for creating SleekXMPP plugins.
 | 
			
		||||
    as a tutorial for creating Slixmpp plugins.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    from sleekxmpp.plugins.base import base_plugin
 | 
			
		||||
    from slixmpp.plugins.base import BasePlugin
 | 
			
		||||
 | 
			
		||||
    class xep_0077(base_plugin):
 | 
			
		||||
    class xep_0077(BasePlugin):
 | 
			
		||||
        """
 | 
			
		||||
        XEP-0077 In-Band Registration
 | 
			
		||||
        """
 | 
			
		||||
@@ -68,7 +68,7 @@ attribute.
 | 
			
		||||
            self.xep = "0077"
 | 
			
		||||
 | 
			
		||||
Now that we have a basic plugin, we need to edit
 | 
			
		||||
``sleekxmpp/plugins/__init__.py`` to include our new plugin by adding
 | 
			
		||||
``slixmpp/plugins/__init__.py`` to include our new plugin by adding
 | 
			
		||||
``'xep_0077'`` to the ``__all__`` declaration.
 | 
			
		||||
 | 
			
		||||
Interacting with Other Plugins
 | 
			
		||||
@@ -81,20 +81,20 @@ call in a method named ``post_init`` which will be called once the plugin has
 | 
			
		||||
been loaded; by doing so we advertise that we can do registrations only after we
 | 
			
		||||
finish activating the plugin.
 | 
			
		||||
 | 
			
		||||
The ``post_init`` method needs to call ``base_plugin.post_init(self)``
 | 
			
		||||
The ``post_init`` method needs to call ``BasePlugin.post_init(self)``
 | 
			
		||||
which will mark that ``post_init`` has been called for the plugin. Once the
 | 
			
		||||
SleekXMPP object begins processing, ``post_init`` will be called on any plugins
 | 
			
		||||
Slixmpp object begins processing, ``post_init`` will be called on any plugins
 | 
			
		||||
that have not already run ``post_init``. This allows you to register plugins and
 | 
			
		||||
their dependencies without needing to worry about the order in which you do so.
 | 
			
		||||
 | 
			
		||||
**Note:** by adding this call we have introduced a dependency on the XEP-0030
 | 
			
		||||
plugin. Be sure to register ``'xep_0030'`` as well as ``'xep_0077'``. SleekXMPP
 | 
			
		||||
plugin. Be sure to register ``'xep_0030'`` as well as ``'xep_0077'``. Slixmpp
 | 
			
		||||
does not automatically load plugin dependencies for you.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def post_init(self):
 | 
			
		||||
        base_plugin.post_init(self)
 | 
			
		||||
        BasePlugin.post_init(self)
 | 
			
		||||
        self.xmpp['xep_0030'].add_feature("jabber:iq:register")
 | 
			
		||||
 | 
			
		||||
Creating Custom Stanza Objects
 | 
			
		||||
@@ -141,7 +141,7 @@ behaviour:
 | 
			
		||||
    **Note:** The accessor methods currently use title case, and not camel case.
 | 
			
		||||
    Thus if you need to access an item named ``"methodName"`` you will need to
 | 
			
		||||
    use ``getMethodname``. This naming convention might change to full camel
 | 
			
		||||
    case in a future version of SleekXMPP.
 | 
			
		||||
    case in a future version of Slixmpp.
 | 
			
		||||
 | 
			
		||||
* ``sub_interfaces``
 | 
			
		||||
    A subset of ``interfaces``, but these keys map to the text of any
 | 
			
		||||
@@ -156,8 +156,8 @@ behaviour:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    from sleekxmpp.xmlstream import ElementBase, ET, JID, register_stanza_plugin
 | 
			
		||||
    from sleekxmpp import Iq
 | 
			
		||||
    from slixmpp.xmlstream import ElementBase, ET, JID, register_stanza_plugin
 | 
			
		||||
    from slixmpp import Iq
 | 
			
		||||
 | 
			
		||||
    class Registration(ElementBase):
 | 
			
		||||
        namespace = 'jabber:iq:register'
 | 
			
		||||
@@ -209,7 +209,7 @@ registration to our ``plugin_init`` method.
 | 
			
		||||
 | 
			
		||||
Also, we need to associate our ``Registration`` class with IQ stanzas;
 | 
			
		||||
that requires the use of the ``register_stanza_plugin`` function (in
 | 
			
		||||
``sleekxmpp.xmlstream.stanzabase``) which takes the class of a parent stanza
 | 
			
		||||
``slixmpp.xmlstream.stanzabase``) which takes the class of a parent stanza
 | 
			
		||||
type followed by the substanza type. In our case, the parent stanza is an IQ
 | 
			
		||||
stanza, and the substanza is our registration query.
 | 
			
		||||
 | 
			
		||||
@@ -222,7 +222,7 @@ handler function to process registration requests.
 | 
			
		||||
        self.description = "In-Band Registration"
 | 
			
		||||
        self.xep = "0077"
 | 
			
		||||
 | 
			
		||||
        self.xmpp.registerHandler(
 | 
			
		||||
        self.xmpp.register_handler(
 | 
			
		||||
          Callback('In-Band Registration',
 | 
			
		||||
            MatchXPath('{%s}iq/{jabber:iq:register}query' % self.xmpp.default_ns),
 | 
			
		||||
            self.__handleRegistration))
 | 
			
		||||
@@ -347,7 +347,7 @@ method ``setForm`` which will take the names of the fields we wish to include.
 | 
			
		||||
                # Add a blank field
 | 
			
		||||
                reg.addField(field)
 | 
			
		||||
 | 
			
		||||
        iq.reply().setPayload(reg.xml)
 | 
			
		||||
        iq.reply().set_payload(reg.xml)
 | 
			
		||||
        iq.send()
 | 
			
		||||
 | 
			
		||||
Note how we are able to access our ``Registration`` stanza object with
 | 
			
		||||
@@ -421,7 +421,7 @@ to the IQ reply.
 | 
			
		||||
    ...
 | 
			
		||||
 | 
			
		||||
    def _sendError(self, iq, code, error_type, name, text=''):
 | 
			
		||||
        iq.reply().setPayload(iq['register'].xml)
 | 
			
		||||
        iq.reply().set_payload(iq['register'].xml)
 | 
			
		||||
        iq.error()
 | 
			
		||||
        iq['error']['code'] = code
 | 
			
		||||
        iq['error']['type'] = error_type
 | 
			
		||||
@@ -464,7 +464,7 @@ component examples below for how to respond to this event.
 | 
			
		||||
            if self.backend.register(iq['from'].bare, iq['register']):
 | 
			
		||||
                # Successful registration
 | 
			
		||||
                self.xmpp.event('registered_user', iq)
 | 
			
		||||
                iq.reply().setPayload(iq['register'].xml)
 | 
			
		||||
                iq.reply().set_payload(iq['register'].xml)
 | 
			
		||||
                iq.send()
 | 
			
		||||
            else:
 | 
			
		||||
                # Conflicting registration
 | 
			
		||||
@@ -484,15 +484,15 @@ and that we specified the form fields we wish to use with
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import sleekxmpp.componentxmpp
 | 
			
		||||
    import slixmpp.componentxmpp
 | 
			
		||||
 | 
			
		||||
    class Example(sleekxmpp.componentxmpp.ComponentXMPP):
 | 
			
		||||
    class Example(slixmpp.componentxmpp.ComponentXMPP):
 | 
			
		||||
 | 
			
		||||
        def __init__(self, jid, password):
 | 
			
		||||
            sleekxmpp.componentxmpp.ComponentXMPP.__init__(self, jid, password, 'localhost', 8888)
 | 
			
		||||
            slixmpp.componentxmpp.ComponentXMPP.__init__(self, jid, password, 'localhost', 8888)
 | 
			
		||||
 | 
			
		||||
            self.registerPlugin('xep_0030')
 | 
			
		||||
            self.registerPlugin('xep_0077')
 | 
			
		||||
            self.register_plugin('xep_0030')
 | 
			
		||||
            self.register_plugin('xep_0077')
 | 
			
		||||
            self.plugin['xep_0077'].setForm('username', 'password')
 | 
			
		||||
 | 
			
		||||
            self.add_event_handler("registered_user", self.reg)
 | 
			
		||||
@@ -500,11 +500,11 @@ and that we specified the form fields we wish to use with
 | 
			
		||||
 | 
			
		||||
        def reg(self, iq):
 | 
			
		||||
            msg = "Welcome! %s" % iq['register']['username']
 | 
			
		||||
            self.sendMessage(iq['from'], msg, mfrom=self.fulljid)
 | 
			
		||||
            self.send_message(iq['from'], msg, mfrom=self.fulljid)
 | 
			
		||||
 | 
			
		||||
        def unreg(self, iq):
 | 
			
		||||
            msg = "Bye! %s" % iq['register']['username']
 | 
			
		||||
            self.sendMessage(iq['from'], msg, mfrom=self.fulljid)
 | 
			
		||||
            self.send_message(iq['from'], msg, mfrom=self.fulljid)
 | 
			
		||||
 | 
			
		||||
**Congratulations!** We now have a basic, functioning implementation of
 | 
			
		||||
XEP-0077.
 | 
			
		||||
@@ -517,17 +517,17 @@ with some additional registration fields implemented.
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    Creating a SleekXMPP Plugin
 | 
			
		||||
    Creating a Slixmpp Plugin
 | 
			
		||||
 | 
			
		||||
    This is a minimal implementation of XEP-0077 to serve
 | 
			
		||||
    as a tutorial for creating SleekXMPP plugins.
 | 
			
		||||
    as a tutorial for creating Slixmpp plugins.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    from sleekxmpp.plugins.base import base_plugin
 | 
			
		||||
    from sleekxmpp.xmlstream.handler.callback import Callback
 | 
			
		||||
    from sleekxmpp.xmlstream.matcher.xpath import MatchXPath
 | 
			
		||||
    from sleekxmpp.xmlstream import ElementBase, ET, JID, register_stanza_plugin
 | 
			
		||||
    from sleekxmpp import Iq
 | 
			
		||||
    from slixmpp.plugins.base import BasePlugin
 | 
			
		||||
    from slixmpp.xmlstream.handler.callback import Callback
 | 
			
		||||
    from slixmpp.xmlstream.matcher.xpath import MatchXPath
 | 
			
		||||
    from slixmpp.xmlstream import ElementBase, ET, JID, register_stanza_plugin
 | 
			
		||||
    from slixmpp import Iq
 | 
			
		||||
    import copy
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -535,9 +535,9 @@ with some additional registration fields implemented.
 | 
			
		||||
        namespace = 'jabber:iq:register'
 | 
			
		||||
        name = 'query'
 | 
			
		||||
        plugin_attrib = 'register'
 | 
			
		||||
        interfaces = set(('username', 'password', 'email', 'nick', 'name', 
 | 
			
		||||
                          'first', 'last', 'address', 'city', 'state', 'zip', 
 | 
			
		||||
                          'phone', 'url', 'date', 'misc', 'text', 'key', 
 | 
			
		||||
        interfaces = set(('username', 'password', 'email', 'nick', 'name',
 | 
			
		||||
                          'first', 'last', 'address', 'city', 'state', 'zip',
 | 
			
		||||
                          'phone', 'url', 'date', 'misc', 'text', 'key',
 | 
			
		||||
                          'registered', 'remove', 'instructions'))
 | 
			
		||||
        sub_interfaces = interfaces
 | 
			
		||||
 | 
			
		||||
@@ -589,7 +589,7 @@ with some additional registration fields implemented.
 | 
			
		||||
        def unregister(self, jid):
 | 
			
		||||
            del self.users[jid]
 | 
			
		||||
 | 
			
		||||
    class xep_0077(base_plugin):
 | 
			
		||||
    class xep_0077(BasePlugin):
 | 
			
		||||
        """
 | 
			
		||||
        XEP-0077 In-Band Registration
 | 
			
		||||
        """
 | 
			
		||||
@@ -601,14 +601,14 @@ with some additional registration fields implemented.
 | 
			
		||||
            self.form_instructions = ""
 | 
			
		||||
            self.backend = UserStore()
 | 
			
		||||
 | 
			
		||||
            self.xmpp.registerHandler(
 | 
			
		||||
            self.xmpp.register_handler(
 | 
			
		||||
                Callback('In-Band Registration',
 | 
			
		||||
                         MatchXPath('{%s}iq/{jabber:iq:register}query' % self.xmpp.default_ns),
 | 
			
		||||
                         self.__handleRegistration))
 | 
			
		||||
            register_stanza_plugin(Iq, Registration)
 | 
			
		||||
 | 
			
		||||
        def post_init(self):
 | 
			
		||||
            base_plugin.post_init(self)
 | 
			
		||||
            BasePlugin.post_init(self)
 | 
			
		||||
            self.xmpp['xep_0030'].add_feature("jabber:iq:register")
 | 
			
		||||
 | 
			
		||||
        def __handleRegistration(self, iq):
 | 
			
		||||
@@ -634,8 +634,9 @@ with some additional registration fields implemented.
 | 
			
		||||
                if self.backend.register(iq['from'].bare, iq['register']):
 | 
			
		||||
                    # Successful registration
 | 
			
		||||
                    self.xmpp.event('registered_user', iq)
 | 
			
		||||
                    iq.reply().setPayload(iq['register'].xml)
 | 
			
		||||
                    iq.send()
 | 
			
		||||
                    reply = iq.reply()
 | 
			
		||||
                    reply.set_payload(iq['register'].xml)
 | 
			
		||||
                    reply.send()
 | 
			
		||||
                else:
 | 
			
		||||
                    # Conflicting registration
 | 
			
		||||
                    self._sendError(iq, '409', 'cancel', 'conflict',
 | 
			
		||||
@@ -666,14 +667,16 @@ with some additional registration fields implemented.
 | 
			
		||||
                    # Add a blank field
 | 
			
		||||
                    reg.addField(field)
 | 
			
		||||
 | 
			
		||||
            iq.reply().setPayload(reg.xml)
 | 
			
		||||
            iq.send()
 | 
			
		||||
            reply = iq.reply()
 | 
			
		||||
            reply.set_payload(reg.xml)
 | 
			
		||||
            reply.send()
 | 
			
		||||
 | 
			
		||||
        def _sendError(self, iq, code, error_type, name, text=''):
 | 
			
		||||
            iq.reply().setPayload(iq['register'].xml)
 | 
			
		||||
            iq.error()
 | 
			
		||||
            iq['error']['code'] = code
 | 
			
		||||
            iq['error']['type'] = error_type
 | 
			
		||||
            iq['error']['condition'] = name
 | 
			
		||||
            iq['error']['text'] = text
 | 
			
		||||
            iq.send()
 | 
			
		||||
            reply = iq.reply()
 | 
			
		||||
            reply.set_payload(iq['register'].xml)
 | 
			
		||||
            reply.error()
 | 
			
		||||
            reply['error']['code'] = code
 | 
			
		||||
            reply['error']['type'] = error_type
 | 
			
		||||
            reply['error']['condition'] = name
 | 
			
		||||
            reply['error']['text'] = text
 | 
			
		||||
            reply.send()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								docs/differences.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								docs/differences.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
.. _differences:
 | 
			
		||||
 | 
			
		||||
Differences from SleekXMPP
 | 
			
		||||
==========================
 | 
			
		||||
 | 
			
		||||
**Python 3.4+ only**
 | 
			
		||||
    slixmpp will only work on python 3.4 and above.
 | 
			
		||||
 | 
			
		||||
**Stanza copies**
 | 
			
		||||
    The same stanza object is given through all the handlers; a handler that
 | 
			
		||||
    edits the stanza object should make its own copy.
 | 
			
		||||
 | 
			
		||||
**Replies**
 | 
			
		||||
    Because stanzas are not copied anymore,
 | 
			
		||||
    :meth:`Stanza.reply() <.StanzaBase.reply>` calls
 | 
			
		||||
    (for :class:`IQs <.Iq>`, :class:`Messages <.Message>`, etc)
 | 
			
		||||
    now return a new object instead of editing the stanza object
 | 
			
		||||
    in-place.
 | 
			
		||||
 | 
			
		||||
**Block and threaded arguments**
 | 
			
		||||
    All the functions that had a ``threaded=`` or ``block=`` argument
 | 
			
		||||
    do not have it anymore. Also, :meth:`.Iq.send` **does not block
 | 
			
		||||
    anymore**.
 | 
			
		||||
 | 
			
		||||
**Coroutine facilities**
 | 
			
		||||
    **See** :ref:`using_asyncio`
 | 
			
		||||
 | 
			
		||||
    If an event handler is a coroutine, it will be called asynchronously
 | 
			
		||||
    in the event loop instead of inside the event caller.
 | 
			
		||||
 | 
			
		||||
    A CoroutineCallback class has been added to create coroutine stream
 | 
			
		||||
    handlers, which will be also handled in the event loop.
 | 
			
		||||
 | 
			
		||||
    The :class:`~.slixmpp.stanza.Iq` object’s :meth:`~.slixmpp.stanza.Iq.send`
 | 
			
		||||
    method now **always** return a :class:`~.asyncio.Future` which result will be set
 | 
			
		||||
    to the IQ reply when it is received, or to ``None`` if the IQ is not of
 | 
			
		||||
    type ``get`` or ``set``.
 | 
			
		||||
 | 
			
		||||
    Many plugins (WIP) calls which retrieve information also return the same
 | 
			
		||||
    future.
 | 
			
		||||
 | 
			
		||||
**Architectural differences**
 | 
			
		||||
    slixmpp does not have an event queue anymore, and instead processes
 | 
			
		||||
    handlers directly after receiving the XML stanza.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
    If you find something that doesn’t work but should, please report it.
 | 
			
		||||
@@ -6,27 +6,33 @@ Event Index
 | 
			
		||||
 | 
			
		||||
    connected
 | 
			
		||||
        - **Data:** ``{}``
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.clientxmpp.ClientXMPP`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.xmlstream.XMLstream`
 | 
			
		||||
 | 
			
		||||
        Signal that a connection has been made with the XMPP server, but a session
 | 
			
		||||
        has not yet been established.
 | 
			
		||||
 | 
			
		||||
    connection_failed
 | 
			
		||||
        - **Data:** ``{}`` or ``Failure Stanza`` if available
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.xmlstream.XMLstream`
 | 
			
		||||
 | 
			
		||||
        Signal that a connection can not be established after number of attempts.
 | 
			
		||||
 | 
			
		||||
    changed_status
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.roster.item.RosterItem`
 | 
			
		||||
 | 
			
		||||
        Triggered when a presence stanza is received from a JID with a show type
 | 
			
		||||
        different than the last presence stanza from the same JID.
 | 
			
		||||
 | 
			
		||||
    changed_subscription
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        Triggered whenever a presence stanza with a type of ``subscribe``,
 | 
			
		||||
        ``subscribed``, ``unsubscribe``, or ``unsubscribed`` is received.
 | 
			
		||||
 | 
			
		||||
        Note that if the values ``xmpp.auto_authorize`` and ``xmpp.auto_subscribe``
 | 
			
		||||
        are set to ``True`` or ``False``, and not ``None``, then SleekXMPP will
 | 
			
		||||
        are set to ``True`` or ``False``, and not ``None``, then Slixmpp will
 | 
			
		||||
        either accept or reject all subscription requests before your event handlers
 | 
			
		||||
        are called. Set these values to ``None`` if you wish to make more complex
 | 
			
		||||
        subscription decisions.
 | 
			
		||||
@@ -52,21 +58,21 @@ Event Index
 | 
			
		||||
        - **Source:**
 | 
			
		||||
 | 
			
		||||
    disco_info
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.plugins.xep_0030.stanza.DiscoInfo`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0030.disco.xep_0030`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.plugins.xep_0030.stanza.DiscoInfo`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0030.disco.xep_0030`
 | 
			
		||||
 | 
			
		||||
        Triggered whenever a ``disco#info`` result stanza is received.
 | 
			
		||||
 | 
			
		||||
    disco_items
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.plugins.xep_0030.stanza.DiscoItems`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0030.disco.xep_0030`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.plugins.xep_0030.stanza.DiscoItems`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0030.disco.xep_0030`
 | 
			
		||||
 | 
			
		||||
        Triggered whenever a ``disco#items`` result stanza is received.
 | 
			
		||||
 | 
			
		||||
    disconnected
 | 
			
		||||
        - **Data:** ``{}``
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.ClientXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.xmlstream.XMLstream`
 | 
			
		||||
 | 
			
		||||
        Signal that the connection with the XMPP server has been lost.
 | 
			
		||||
 | 
			
		||||
    entity_time
 | 
			
		||||
@@ -75,34 +81,34 @@ Event Index
 | 
			
		||||
 | 
			
		||||
    failed_auth
 | 
			
		||||
        - **Data:** ``{}``
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.ClientXMPP`, :py:class:`~sleekxmpp.plugins.xep_0078.xep_0078`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.ClientXMPP`, :py:class:`~slixmpp.plugins.xep_0078.xep_0078`
 | 
			
		||||
 | 
			
		||||
        Signal that the server has rejected the provided login credentials.
 | 
			
		||||
 | 
			
		||||
    gmail_notify
 | 
			
		||||
        - **Data:** ``{}``
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.gmail_notify.gmail_notify`
 | 
			
		||||
        
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.gmail_notify.gmail_notify`
 | 
			
		||||
 | 
			
		||||
        Signal that there are unread emails for the Gmail account associated with the current XMPP account.
 | 
			
		||||
 | 
			
		||||
    gmail_messages
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Iq`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.gmail_notify.gmail_notify`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Iq`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.gmail_notify.gmail_notify`
 | 
			
		||||
 | 
			
		||||
        Signal that there are unread emails for the Gmail account associated with the current XMPP account.
 | 
			
		||||
 | 
			
		||||
    got_online
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.roster.item.RosterItem`
 | 
			
		||||
 | 
			
		||||
        If a presence stanza is received from a JID which was previously marked as
 | 
			
		||||
        offline, and the presence has a show type of '``chat``', '``dnd``', '``away``',
 | 
			
		||||
        or '``xa``', then this event is triggered as well.
 | 
			
		||||
 | 
			
		||||
    got_offline
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.roster.item.RosterItem`
 | 
			
		||||
 | 
			
		||||
        Signal that an unavailable presence stanza has been received from a JID.
 | 
			
		||||
 | 
			
		||||
    groupchat_invite
 | 
			
		||||
@@ -110,25 +116,25 @@ Event Index
 | 
			
		||||
        - **Source:**
 | 
			
		||||
 | 
			
		||||
    groupchat_direct_invite
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Message` 
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0249.direct`
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Message`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0249.direct`
 | 
			
		||||
 | 
			
		||||
    groupchat_message
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Message`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0045.xep_0045`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Message`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0045.xep_0045`
 | 
			
		||||
 | 
			
		||||
        Triggered whenever a message is received from a multi-user chat room.
 | 
			
		||||
 | 
			
		||||
    groupchat_presence
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0045.xep_0045`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0045.xep_0045`
 | 
			
		||||
 | 
			
		||||
        Triggered whenever a presence stanza is received from a user in a multi-user chat room.
 | 
			
		||||
 | 
			
		||||
    groupchat_subject
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Message`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0045.xep_0045`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Message`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0045.xep_0045`
 | 
			
		||||
 | 
			
		||||
        Triggered whenever the subject of a multi-user chat room is changed, or announced when joining a room.
 | 
			
		||||
 | 
			
		||||
    killed
 | 
			
		||||
@@ -140,25 +146,32 @@ Event Index
 | 
			
		||||
        - **Source:**
 | 
			
		||||
 | 
			
		||||
    message
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Message`
 | 
			
		||||
        - **Source:** :py:class:`BaseXMPP <sleekxmpp.BaseXMPP>`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Message`
 | 
			
		||||
        - **Source:** :py:class:`BaseXMPP <slixmpp.BaseXMPP>`
 | 
			
		||||
 | 
			
		||||
        Makes the contents of message stanzas available whenever one is received. Be
 | 
			
		||||
        sure to check the message type in order to handle error messages.
 | 
			
		||||
 | 
			
		||||
    message_error
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Message`
 | 
			
		||||
        - **Source:** :py:class:`BaseXMPP <slixmpp.BaseXMPP>`
 | 
			
		||||
 | 
			
		||||
        Makes the contents of message stanzas available whenever one is received.
 | 
			
		||||
        Only handler messages with an ``error`` type.
 | 
			
		||||
 | 
			
		||||
    message_form
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.plugins.xep_0004.Form` 
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0004.xep_0004` 
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.plugins.xep_0004.Form`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0004.xep_0004`
 | 
			
		||||
 | 
			
		||||
        Currently the same as :term:`message_xform`.
 | 
			
		||||
 | 
			
		||||
    message_xform
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.plugins.xep_0004.Form` 
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0004.xep_0004` 
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.plugins.xep_0004.Form`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0004.xep_0004`
 | 
			
		||||
 | 
			
		||||
        Triggered whenever a data form is received inside a message.
 | 
			
		||||
 | 
			
		||||
    mucc::[room]::got_offline
 | 
			
		||||
    muc::[room]::got_offline
 | 
			
		||||
        - **Data:**
 | 
			
		||||
        - **Source:**
 | 
			
		||||
 | 
			
		||||
@@ -175,76 +188,74 @@ Event Index
 | 
			
		||||
        - **Source:**
 | 
			
		||||
 | 
			
		||||
    presence_available
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        A presence stanza with a type of '``available``' is received.
 | 
			
		||||
 | 
			
		||||
    presence_error
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        A presence stanza with a type of '``error``' is received.
 | 
			
		||||
 | 
			
		||||
    presence_form
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.plugins.xep_0004.Form` 
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.plugins.xep_0004.xep_0004` 
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.plugins.xep_0004.Form`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.plugins.xep_0004.xep_0004`
 | 
			
		||||
 | 
			
		||||
        This event is present in the XEP-0004 plugin code, but is currently not used.
 | 
			
		||||
 | 
			
		||||
    presence_probe
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        A presence stanza with a type of '``probe``' is received.
 | 
			
		||||
 | 
			
		||||
    presence_subscribe
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        A presence stanza with a type of '``subscribe``' is received.
 | 
			
		||||
 | 
			
		||||
    presence_subscribed
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        A presence stanza with a type of '``subscribed``' is received.
 | 
			
		||||
 | 
			
		||||
    presence_unavailable
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        A presence stanza with a type of '``unavailable``' is received.
 | 
			
		||||
 | 
			
		||||
    presence_unsubscribe
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        A presence stanza with a type of '``unsubscribe``' is received.
 | 
			
		||||
 | 
			
		||||
    presence_unsubscribed
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.Presence`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 | 
			
		||||
        A presence stanza with a type of '``unsubscribed``' is received.
 | 
			
		||||
 | 
			
		||||
    roster_update
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.stanza.Roster` 
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.ClientXMPP` 
 | 
			
		||||
        
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.stanza.Roster`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.ClientXMPP`
 | 
			
		||||
 | 
			
		||||
        An IQ result containing roster entries is received.
 | 
			
		||||
 | 
			
		||||
    sent_presence
 | 
			
		||||
        - **Data:** ``{}``
 | 
			
		||||
        - **Source:** :py:class:`BaseXMPP <sleekxmpp.BaseXMPP>`
 | 
			
		||||
        
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.roster.multi.Roster`
 | 
			
		||||
 | 
			
		||||
        Signal that an initial presence stanza has been written to the XML stream.
 | 
			
		||||
 | 
			
		||||
    session_end
 | 
			
		||||
        - **Data:** ``{}``
 | 
			
		||||
        - **Source:** :py:class:`ClientXMPP <sleekxmpp.ClientXMPP>`, 
 | 
			
		||||
          :py:class:`ComponentXMPP <sleekxmpp.ComponentXMPP>`
 | 
			
		||||
          :py:class:`XEP-0078 <sleekxmpp.plugins.xep_0078>`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.xmlstream.XMLstream`
 | 
			
		||||
 | 
			
		||||
        Signal that a connection to the XMPP server has been lost and the current
 | 
			
		||||
        stream session has ended. Currently equivalent to :term:`disconnected`, but
 | 
			
		||||
@@ -256,16 +267,16 @@ Event Index
 | 
			
		||||
 | 
			
		||||
    session_start
 | 
			
		||||
        - **Data:** ``{}``
 | 
			
		||||
        - **Source:** :py:class:`ClientXMPP <sleekxmpp.ClientXMPP>`, 
 | 
			
		||||
          :py:class:`ComponentXMPP <sleekxmpp.ComponentXMPP>`
 | 
			
		||||
          :py:class:`XEP-0078 <sleekxmpp.plugins.xep_0078>`
 | 
			
		||||
        - **Source:** :py:class:`ClientXMPP <slixmpp.ClientXMPP>`,
 | 
			
		||||
          :py:class:`ComponentXMPP <slixmpp.ComponentXMPP>`
 | 
			
		||||
          :py:class:`XEP-0078 <slixmpp.plugins.xep_0078>`
 | 
			
		||||
 | 
			
		||||
        Signal that a connection to the XMPP server has been made and a session has been established.
 | 
			
		||||
 | 
			
		||||
    socket_error
 | 
			
		||||
        - **Data:** ``Socket`` exception object 
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.xmlstream.XMLstream`
 | 
			
		||||
        - **Data:** ``Socket`` exception object
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.xmlstream.XMLstream`
 | 
			
		||||
 | 
			
		||||
    stream_error
 | 
			
		||||
        - **Data:** :py:class:`~sleekxmpp.stanza.StreamError`
 | 
			
		||||
        - **Source:** :py:class:`~sleekxmpp.BaseXMPP`
 | 
			
		||||
        - **Data:** :py:class:`~slixmpp.stanza.StreamError`
 | 
			
		||||
        - **Source:** :py:class:`~slixmpp.BaseXMPP`
 | 
			
		||||
 
 | 
			
		||||
@@ -5,24 +5,16 @@ Create and Run a Server Component
 | 
			
		||||
=================================
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    If you have any issues working through this quickstart guide
 | 
			
		||||
    or the other tutorials here, please either send a message to the
 | 
			
		||||
    `mailing list <http://groups.google.com/group/sleekxmpp-discussion>`_
 | 
			
		||||
    or join the chat room at `sleek@conference.jabber.org
 | 
			
		||||
    <xmpp:sleek@conference.jabber.org?join>`_.
 | 
			
		||||
    join the chat room at `slixmpp@muc.poez.io
 | 
			
		||||
    <xmpp:slixmpp@muc.poez.io?join>`_.
 | 
			
		||||
 | 
			
		||||
If you have not yet installed SleekXMPP, do so now by either checking out a version
 | 
			
		||||
from `Github <http://github.com/fritzy/SleekXMPP>`_, or installing it using ``pip``
 | 
			
		||||
or ``easy_install``.
 | 
			
		||||
If you have not yet installed Slixmpp, do so now by either checking out a version
 | 
			
		||||
with `Git <http://git.poez.io/slixmpp>`_.
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    pip install sleekxmpp  # Or: easy_install sleekxmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Many XMPP applications eventually graduate to requiring to run as a server 
 | 
			
		||||
component in order to meet scalability requirements. To demonstrate how to 
 | 
			
		||||
Many XMPP applications eventually graduate to requiring to run as a server
 | 
			
		||||
component in order to meet scalability requirements. To demonstrate how to
 | 
			
		||||
turn an XMPP client bot into a component, we'll turn the echobot example
 | 
			
		||||
(:ref:`echobot`) into a component version.
 | 
			
		||||
 | 
			
		||||
@@ -30,7 +22,7 @@ The first difference is that we will add an additional import statement:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    from sleekxmpp.componentxmpp import ComponentXMPP
 | 
			
		||||
    from slixmpp.componentxmpp import ComponentXMPP
 | 
			
		||||
 | 
			
		||||
Likewise, we will change the bot's class definition to match:
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +40,7 @@ a MUC component, the following could be used:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    muc = ComponentXMPP('muc.sleekxmpp.com', '******', 'sleekxmpp.com', 5555)
 | 
			
		||||
    muc = ComponentXMPP('muc.slixmpp.com', '******', 'slixmpp.com', 5555)
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
@@ -62,10 +54,10 @@ with presence.
 | 
			
		||||
The other, main difference with components is that the
 | 
			
		||||
``'from'`` value for every stanza must be explicitly set, since
 | 
			
		||||
components may send stanzas from multiple JIDs. To do so,
 | 
			
		||||
the :meth:`~sleekxmpp.basexmpp.BaseXMPP.send_message()` and
 | 
			
		||||
:meth:`~sleekxmpp.basexmpp.BaseXMPP.send_presence()` accept the parameters
 | 
			
		||||
the :meth:`~slixmpp.basexmpp.BaseXMPP.send_message()` and
 | 
			
		||||
:meth:`~slixmpp.basexmpp.BaseXMPP.send_presence()` accept the parameters
 | 
			
		||||
``mfrom`` and ``pfrom``, respectively. For any method that uses
 | 
			
		||||
:class:`~sleekxmpp.stanza.iq.Iq` stanzas, ``ifrom`` may be used.
 | 
			
		||||
:class:`~slixmpp.stanza.iq.Iq` stanzas, ``ifrom`` may be used.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Final Product
 | 
			
		||||
 
 | 
			
		||||
@@ -1,25 +1,17 @@
 | 
			
		||||
.. _echobot:
 | 
			
		||||
 | 
			
		||||
===============================
 | 
			
		||||
SleekXMPP Quickstart - Echo Bot
 | 
			
		||||
Slixmpp Quickstart - Echo Bot
 | 
			
		||||
===============================
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    If you have any issues working through this quickstart guide
 | 
			
		||||
    or the other tutorials here, please either send a message to the
 | 
			
		||||
    `mailing list <http://groups.google.com/group/sleekxmpp-discussion>`_
 | 
			
		||||
    or join the chat room at `sleek@conference.jabber.org
 | 
			
		||||
    <xmpp:sleek@conference.jabber.org?join>`_.
 | 
			
		||||
 | 
			
		||||
If you have not yet installed SleekXMPP, do so now by either checking out a version
 | 
			
		||||
from `Github <http://github.com/fritzy/SleekXMPP>`_, or installing it using ``pip``
 | 
			
		||||
or ``easy_install``.
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    pip install sleekxmpp  # Or: easy_install sleekxmpp
 | 
			
		||||
    join the chat room at `slixmpp@muc.poez.io
 | 
			
		||||
    <xmpp:slixmpp@muc.poez.io?join>`_.
 | 
			
		||||
 | 
			
		||||
If you have not yet installed Slixmpp, do so now by either checking out a version
 | 
			
		||||
with `Git <http://git.poez.io/slixmpp>`_.
 | 
			
		||||
 | 
			
		||||
As a basic starting project, we will create an echo bot which will reply to any
 | 
			
		||||
messages sent to it. We will also go through adding some basic command line configuration
 | 
			
		||||
@@ -44,11 +36,12 @@ To get started, here is a brief outline of the structure that the final project
 | 
			
		||||
    # -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
    import sys
 | 
			
		||||
    import asyncio
 | 
			
		||||
    import logging
 | 
			
		||||
    import getpass
 | 
			
		||||
    from optparse import OptionParser
 | 
			
		||||
 | 
			
		||||
    import sleekxmpp
 | 
			
		||||
    import slixmpp
 | 
			
		||||
 | 
			
		||||
    '''Here we will create out echo bot class'''
 | 
			
		||||
 | 
			
		||||
@@ -59,24 +52,6 @@ To get started, here is a brief outline of the structure that the final project
 | 
			
		||||
 | 
			
		||||
        '''Finally, we connect the bot and start listening for messages'''
 | 
			
		||||
 | 
			
		||||
Default Encoding
 | 
			
		||||
----------------
 | 
			
		||||
XMPP requires support for UTF-8 and so SleekXMPP must use UTF-8 as well. In
 | 
			
		||||
Python3 this is simple because Unicode is the default string type. For Python2.6+
 | 
			
		||||
the situation is not as easy because standard strings are simply byte arrays and
 | 
			
		||||
use ASCII. We can get Python to use UTF-8 as the default encoding by including:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    if sys.version_info < (3, 0):
 | 
			
		||||
        from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
        setdefaultencoding('utf8')
 | 
			
		||||
 | 
			
		||||
.. warning::
 | 
			
		||||
 | 
			
		||||
    Until we are able to ensure that SleekXMPP will always use Unicode in Python2.6+, this
 | 
			
		||||
    may cause issues embedding SleekXMPP into other applications which assume ASCII encoding.
 | 
			
		||||
 | 
			
		||||
Creating the EchoBot Class
 | 
			
		||||
--------------------------
 | 
			
		||||
 | 
			
		||||
@@ -85,15 +60,15 @@ clients. Since our echo bot will only be responding to a few people, and won't n
 | 
			
		||||
to remember thousands of users, we will use a client connection. A client connection
 | 
			
		||||
is the same type that you use with your standard IM client such as Pidgin or Psi.
 | 
			
		||||
 | 
			
		||||
SleekXMPP comes with a :class:`ClientXMPP <sleekxmpp.clientxmpp.ClientXMPP>` class
 | 
			
		||||
which we can extend to add our message echoing feature. :class:`ClientXMPP <sleekxmpp.clientxmpp.ClientXMPP>`
 | 
			
		||||
Slixmpp comes with a :class:`ClientXMPP <slixmpp.clientxmpp.ClientXMPP>` class
 | 
			
		||||
which we can extend to add our message echoing feature. :class:`ClientXMPP <slixmpp.clientxmpp.ClientXMPP>`
 | 
			
		||||
requires the parameters ``jid`` and ``password``, so we will let our ``EchoBot`` class accept those
 | 
			
		||||
as well.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    class EchoBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
        
 | 
			
		||||
    class EchoBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
        def __init__(self, jid, password):
 | 
			
		||||
            super(EchoBot, self).__init__(jid, password)
 | 
			
		||||
 | 
			
		||||
@@ -102,7 +77,7 @@ Handling Session Start
 | 
			
		||||
The XMPP spec requires clients to broadcast its presence and retrieve its roster (buddy list) once
 | 
			
		||||
it connects and establishes a session with the XMPP server. Until these two tasks are completed,
 | 
			
		||||
some servers may not deliver or send messages or presence notifications to the client. So we now
 | 
			
		||||
need to be sure that we retrieve our roster and send an initial presence once the session has 
 | 
			
		||||
need to be sure that we retrieve our roster and send an initial presence once the session has
 | 
			
		||||
started. To do that, we will register an event handler for the :term:`session_start` event.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
@@ -132,8 +107,8 @@ Our event handler, like every event handler, accepts a single parameter which ty
 | 
			
		||||
that was received that caused the event. In this case, ``event`` will just be an empty dictionary since
 | 
			
		||||
there is no associated data.
 | 
			
		||||
 | 
			
		||||
Our first task of sending an initial presence is done using :meth:`send_presence <sleekxmpp.basexmpp.BaseXMPP.send_presence>`.
 | 
			
		||||
Calling :meth:`send_presence <sleekxmpp.basexmpp.BaseXMPP.send_presence>` without any arguments will send the simplest
 | 
			
		||||
Our first task of sending an initial presence is done using :meth:`send_presence <slixmpp.basexmpp.BaseXMPP.send_presence>`.
 | 
			
		||||
Calling :meth:`send_presence <slixmpp.basexmpp.BaseXMPP.send_presence>` without any arguments will send the simplest
 | 
			
		||||
stanza allowed in XMPP:
 | 
			
		||||
 | 
			
		||||
.. code-block:: xml
 | 
			
		||||
@@ -141,17 +116,17 @@ stanza allowed in XMPP:
 | 
			
		||||
    <presence />
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The second requirement is fulfilled using :meth:`get_roster <sleekxmpp.clientxmpp.ClientXMPP.get_roster>`, which
 | 
			
		||||
The second requirement is fulfilled using :meth:`get_roster <slixmpp.clientxmpp.ClientXMPP.get_roster>`, which
 | 
			
		||||
will send an IQ stanza requesting the roster to the server and then wait for the response. You may be wondering
 | 
			
		||||
what :meth:`get_roster <sleekxmpp.clientxmpp.ClientXMPP.get_roster>` returns since we are not saving any return
 | 
			
		||||
what :meth:`get_roster <slixmpp.clientxmpp.ClientXMPP.get_roster>` returns since we are not saving any return
 | 
			
		||||
value. The roster data is saved by an internal handler to ``self.roster``, and in the case of a :class:`ClientXMPP
 | 
			
		||||
<sleekxmpp.clientxmpp.ClientXMPP>` instance to ``self.client_roster``. (The difference between ``self.roster`` and
 | 
			
		||||
<slixmpp.clientxmpp.ClientXMPP>` instance to ``self.client_roster``. (The difference between ``self.roster`` and
 | 
			
		||||
``self.client_roster`` is that ``self.roster`` supports storing roster information for multiple JIDs, which is useful
 | 
			
		||||
for components, whereas ``self.client_roster`` stores roster data for just the client's JID.)
 | 
			
		||||
 | 
			
		||||
It is possible for a timeout to occur while waiting for the server to respond, which can happen if the
 | 
			
		||||
network is excessively slow or the server is no longer responding. In that case, an :class:`IQTimeout
 | 
			
		||||
<sleekxmpp.exceptions.IQTimeout>` is raised. Similarly, an :class:`IQError <sleekxmpp.exceptions.IQError>` exception can
 | 
			
		||||
<slixmpp.exceptions.IQTimeout>` is raised. Similarly, an :class:`IQError <slixmpp.exceptions.IQError>` exception can
 | 
			
		||||
be raised if the request contained bad data or requested the roster for the wrong user. In either case, you can wrap the
 | 
			
		||||
``get_roster()`` call in a ``try``/``except`` block to retry the roster retrieval process.
 | 
			
		||||
 | 
			
		||||
@@ -198,10 +173,10 @@ or ``chat``. (Other potential types are ``error``, ``headline``, and ``groupchat
 | 
			
		||||
 | 
			
		||||
Let's take a closer look at the ``.reply()`` method used above. For message stanzas,
 | 
			
		||||
``.reply()`` accepts the parameter ``body`` (also as the first positional argument),
 | 
			
		||||
which is then used as the value of the ``<body />`` element of the message. 
 | 
			
		||||
which is then used as the value of the ``<body />`` element of the message.
 | 
			
		||||
Setting the appropriate ``to`` JID is also handled by ``.reply()``.
 | 
			
		||||
 | 
			
		||||
Another way to have sent the reply message would be to use :meth:`send_message <sleekxmpp.basexmpp.BaseXMPP.send_message>`,
 | 
			
		||||
Another way to have sent the reply message would be to use :meth:`send_message <slixmpp.basexmpp.BaseXMPP.send_message>`,
 | 
			
		||||
which is a convenience method for generating and sending a message based on the values passed to it. If we were to use
 | 
			
		||||
this method, the above code would look as so:
 | 
			
		||||
 | 
			
		||||
@@ -229,20 +204,20 @@ Whichever method you choose to use, the results in action will look like this:
 | 
			
		||||
    XMPP does not require stanzas sent by a client to include a ``from`` attribute, and
 | 
			
		||||
    leaves that responsibility to the XMPP server. However, if a sent stanza does
 | 
			
		||||
    include a ``from`` attribute, it must match the full JID of the client or some
 | 
			
		||||
    servers will reject it. SleekXMPP thus leaves out the ``from`` attribute when replying
 | 
			
		||||
    servers will reject it. Slixmpp thus leaves out the ``from`` attribute when replying
 | 
			
		||||
    using a client connection.
 | 
			
		||||
 | 
			
		||||
Command Line Arguments and Logging
 | 
			
		||||
----------------------------------
 | 
			
		||||
 | 
			
		||||
While this isn't part of SleekXMPP itself, we do want our echo bot program to be able
 | 
			
		||||
While this isn't part of Slixmpp itself, we do want our echo bot program to be able
 | 
			
		||||
to accept a JID and password from the command line instead of hard coding them. We will
 | 
			
		||||
use the ``optparse`` module for this, though there are several alternative methods, including
 | 
			
		||||
the newer ``argparse`` module.
 | 
			
		||||
 | 
			
		||||
We want to accept three parameters: the JID for the echo bot, its password, and a flag for
 | 
			
		||||
displaying the debugging logs. We also want these to be optional parameters, since passing
 | 
			
		||||
a password directly through the command line can be a security risk. 
 | 
			
		||||
a password directly through the command line can be a security risk.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
@@ -303,21 +278,21 @@ the ``EchoBot.__init__`` method instead.
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    If you are using the OpenFire server, you will need to include an additional 
 | 
			
		||||
    If you are using the OpenFire server, you will need to include an additional
 | 
			
		||||
    configuration step. OpenFire supports a different version of SSL than what
 | 
			
		||||
    most servers and SleekXMPP support.
 | 
			
		||||
    most servers and Slixmpp support.
 | 
			
		||||
 | 
			
		||||
    .. code-block:: python
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
        import ssl
 | 
			
		||||
        xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
Now we're ready to connect and begin echoing messages. If you have the package
 | 
			
		||||
``dnspython`` installed, then the :meth:`sleekxmpp.clientxmpp.ClientXMPP` method
 | 
			
		||||
``aiodns`` installed, then the :meth:`slixmpp.clientxmpp.ClientXMPP` method
 | 
			
		||||
will perform a DNS query to find the appropriate server to connect to for the
 | 
			
		||||
given JID. If you do not have ``dnspython``, then SleekXMPP will attempt to 
 | 
			
		||||
given JID. If you do not have ``aiodns``, then Slixmpp will attempt to
 | 
			
		||||
connect to the hostname used by the JID, unless an address tuple is supplied
 | 
			
		||||
to :meth:`sleekxmpp.clientxmpp.ClientXMPP`. 
 | 
			
		||||
to :meth:`slixmpp.clientxmpp.ClientXMPP`.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
@@ -330,35 +305,19 @@ to :meth:`sleekxmpp.clientxmpp.ClientXMPP`.
 | 
			
		||||
        else:
 | 
			
		||||
            print('Unable to connect')
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    For Google Talk users withouth ``dnspython`` installed, the above code
 | 
			
		||||
    should look like:
 | 
			
		||||
 | 
			
		||||
    .. code-block:: python
 | 
			
		||||
 | 
			
		||||
        if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
            # .. option parsing & echo bot configuration
 | 
			
		||||
 | 
			
		||||
            if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
                xmpp.process(block=True)
 | 
			
		||||
            else:
 | 
			
		||||
                print('Unable to connect')
 | 
			
		||||
 | 
			
		||||
To begin responding to messages, you'll see we called :meth:`sleekxmpp.basexmpp.BaseXMPP.process`
 | 
			
		||||
To begin responding to messages, you'll see we called :meth:`slixmpp.basexmpp.BaseXMPP.process`
 | 
			
		||||
which will start the event handling, send queue, and XML reader threads. It will also call
 | 
			
		||||
the :meth:`sleekxmpp.plugins.base.base_plugin.post_init` method on all registered plugins. By
 | 
			
		||||
passing ``block=True`` to :meth:`sleekxmpp.basexmpp.BaseXMPP.process` we are running the 
 | 
			
		||||
main processing loop in the main thread of execution. The :meth:`sleekxmpp.basexmpp.BaseXMPP.process`
 | 
			
		||||
call will not return until after SleekXMPP disconnects. If you need to run the client in the background
 | 
			
		||||
the :meth:`slixmpp.plugins.base.BasePlugin.post_init` method on all registered plugins. By
 | 
			
		||||
passing ``block=True`` to :meth:`slixmpp.basexmpp.BaseXMPP.process` we are running the
 | 
			
		||||
main processing loop in the main thread of execution. The :meth:`slixmpp.basexmpp.BaseXMPP.process`
 | 
			
		||||
call will not return until after Slixmpp disconnects. If you need to run the client in the background
 | 
			
		||||
for another program, use ``block=False`` to spawn the processing loop in its own thread.
 | 
			
		||||
 | 
			
		||||
.. note:: 
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    Before 1.0, controlling the blocking behaviour of :meth:`sleekxmpp.basexmpp.BaseXMPP.process` was
 | 
			
		||||
    Before 1.0, controlling the blocking behaviour of :meth:`slixmpp.basexmpp.BaseXMPP.process` was
 | 
			
		||||
    done via the ``threaded`` argument. This arrangement was a source of confusion because some users
 | 
			
		||||
    interpreted that as controlling whether or not SleekXMPP used threads at all, instead of how
 | 
			
		||||
    interpreted that as controlling whether or not Slixmpp used threads at all, instead of how
 | 
			
		||||
    the processing loop itself was spawned.
 | 
			
		||||
 | 
			
		||||
    The statements ``xmpp.process(threaded=False)`` and ``xmpp.process(block=True)`` are equivalent.
 | 
			
		||||
@@ -370,7 +329,7 @@ The Final Product
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
Here then is what the final result should look like after working through the guide above. The code
 | 
			
		||||
can also be found in the SleekXMPP `examples directory <http://github.com/fritzy/SleekXMPP/tree/master/examples>`_.
 | 
			
		||||
can also be found in the Slixmpp `examples directory <http://github.com/fritzy/Slixmpp/tree/master/examples>`_.
 | 
			
		||||
 | 
			
		||||
.. compound::
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,17 @@
 | 
			
		||||
Send/Receive IQ Stanzas
 | 
			
		||||
=======================
 | 
			
		||||
 | 
			
		||||
Unlike :class:`~sleekxmpp.stanza.message.Message` and
 | 
			
		||||
:class:`~sleekxmpp.stanza.presence.Presence` stanzas which only use
 | 
			
		||||
text data for basic usage, :class:`~sleekxmpp.stanza.iq.Iq` stanzas
 | 
			
		||||
Unlike :class:`~slixmpp.stanza.message.Message` and
 | 
			
		||||
:class:`~slixmpp.stanza.presence.Presence` stanzas which only use
 | 
			
		||||
text data for basic usage, :class:`~slixmpp.stanza.iq.Iq` stanzas
 | 
			
		||||
require using XML payloads, and generally entail creating a new
 | 
			
		||||
SleekXMPP plugin to provide the necessary convenience methods to
 | 
			
		||||
Slixmpp plugin to provide the necessary convenience methods to
 | 
			
		||||
make working with them easier.
 | 
			
		||||
 | 
			
		||||
Basic Use
 | 
			
		||||
---------
 | 
			
		||||
 | 
			
		||||
XMPP's use of :class:`~sleekxmpp.stanza.iq.Iq` stanzas is built around
 | 
			
		||||
XMPP's use of :class:`~slixmpp.stanza.iq.Iq` stanzas is built around
 | 
			
		||||
namespaced ``<query />`` elements. For clients, just sending the
 | 
			
		||||
empty ``<query />`` element will suffice for retrieving information. For
 | 
			
		||||
example, a very basic implementation of service discovery would just
 | 
			
		||||
@@ -26,18 +26,18 @@ need to be able to send:
 | 
			
		||||
Creating Iq Stanzas
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
SleekXMPP provides built-in support for creating basic :class:`~sleekxmpp.stanza.iq.Iq`
 | 
			
		||||
Slixmpp provides built-in support for creating basic :class:`~slixmpp.stanza.iq.Iq`
 | 
			
		||||
stanzas this way. The relevant methods are:
 | 
			
		||||
 | 
			
		||||
* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq`
 | 
			
		||||
* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_get`
 | 
			
		||||
* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_set`
 | 
			
		||||
* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_result`
 | 
			
		||||
* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_error`
 | 
			
		||||
* :meth:`~sleekxmpp.basexmpp.BaseXMPP.make_iq_query`
 | 
			
		||||
* :meth:`~slixmpp.basexmpp.BaseXMPP.make_iq`
 | 
			
		||||
* :meth:`~slixmpp.basexmpp.BaseXMPP.make_iq_get`
 | 
			
		||||
* :meth:`~slixmpp.basexmpp.BaseXMPP.make_iq_set`
 | 
			
		||||
* :meth:`~slixmpp.basexmpp.BaseXMPP.make_iq_result`
 | 
			
		||||
* :meth:`~slixmpp.basexmpp.BaseXMPP.make_iq_error`
 | 
			
		||||
* :meth:`~slixmpp.basexmpp.BaseXMPP.make_iq_query`
 | 
			
		||||
 | 
			
		||||
These methods all follow the same pattern: create or modify an existing 
 | 
			
		||||
:class:`~sleekxmpp.stanza.iq.Iq` stanza, set the ``'type'`` value based
 | 
			
		||||
These methods all follow the same pattern: create or modify an existing
 | 
			
		||||
:class:`~slixmpp.stanza.iq.Iq` stanza, set the ``'type'`` value based
 | 
			
		||||
on the method name, and finally add a ``<query />`` element with the given
 | 
			
		||||
namespace. For example, to produce the query above, you would use:
 | 
			
		||||
 | 
			
		||||
@@ -50,14 +50,14 @@ namespace. For example, to produce the query above, you would use:
 | 
			
		||||
Sending Iq Stanzas
 | 
			
		||||
~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Once an :class:`~sleekxmpp.stanza.iq.Iq` stanza is created, sending it
 | 
			
		||||
over the wire is done using its :meth:`~sleekxmpp.stanza.iq.Iq.send()`
 | 
			
		||||
Once an :class:`~slixmpp.stanza.iq.Iq` stanza is created, sending it
 | 
			
		||||
over the wire is done using its :meth:`~slixmpp.stanza.iq.Iq.send()`
 | 
			
		||||
method, like any other stanza object. However, there are a few extra
 | 
			
		||||
options to control how to wait for the query's response.
 | 
			
		||||
 | 
			
		||||
These options are:
 | 
			
		||||
 | 
			
		||||
* ``block``: The default behaviour is that :meth:`~sleekxmpp.stanza.iq.Iq.send()`
 | 
			
		||||
* ``block``: The default behaviour is that :meth:`~slixmpp.stanza.iq.Iq.send()`
 | 
			
		||||
  will block until a response is received and the response stanza will be the
 | 
			
		||||
  return value. Setting ``block`` to ``False`` will cause the call to return
 | 
			
		||||
  immediately. In which case, you will need to arrange some way to capture
 | 
			
		||||
@@ -74,7 +74,7 @@ These options are:
 | 
			
		||||
  To change the timeout for a single call, the ``timeout`` parameter works:
 | 
			
		||||
 | 
			
		||||
    .. code-block:: python
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        iq.send(timeout=60)
 | 
			
		||||
 | 
			
		||||
* ``callback``: When not using a blocking call, using the ``callback``
 | 
			
		||||
@@ -85,16 +85,16 @@ These options are:
 | 
			
		||||
 | 
			
		||||
    .. code-block:: python
 | 
			
		||||
 | 
			
		||||
       cb_name = iq.send(callback=self.a_callback) 
 | 
			
		||||
       cb_name = iq.send(callback=self.a_callback)
 | 
			
		||||
 | 
			
		||||
       # ... later if we need to cancel
 | 
			
		||||
       self.remove_handler(cb_name)
 | 
			
		||||
 | 
			
		||||
Properly working with :class:`~sleekxmpp.stanza.iq.Iq` stanzas requires
 | 
			
		||||
Properly working with :class:`~slixmpp.stanza.iq.Iq` stanzas requires
 | 
			
		||||
handling the intended, normal flow, error responses, and timed out
 | 
			
		||||
requests. To make this easier, two exceptions may be thrown by
 | 
			
		||||
:meth:`~sleekxmpp.stanza.iq.Iq.send()`: :exc:`~sleekxmpp.exceptions.IqError`
 | 
			
		||||
and :exc:`~sleekxmpp.exceptions.IqTimeout`. These exceptions only
 | 
			
		||||
:meth:`~slixmpp.stanza.iq.Iq.send()`: :exc:`~slixmpp.exceptions.IqError`
 | 
			
		||||
and :exc:`~slixmpp.exceptions.IqTimeout`. These exceptions only
 | 
			
		||||
apply to the default, blocking calls.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
@@ -110,7 +110,7 @@ apply to the default, blocking calls.
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
If you do not care to distinguish between errors and timeouts, then you
 | 
			
		||||
can combine both cases with a generic :exc:`~sleekxmpp.exceptions.XMPPError`
 | 
			
		||||
can combine both cases with a generic :exc:`~slixmpp.exceptions.XMPPError`
 | 
			
		||||
exception:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
@@ -124,24 +124,24 @@ exception:
 | 
			
		||||
Advanced Use
 | 
			
		||||
------------
 | 
			
		||||
 | 
			
		||||
Going beyond the basics provided by SleekXMPP requires building at least a
 | 
			
		||||
rudimentary SleekXMPP plugin to create a :term:`stanza object` for
 | 
			
		||||
interfacting with the :class:`~sleekxmpp.stanza.iq.Iq` payload.
 | 
			
		||||
Going beyond the basics provided by Slixmpp requires building at least a
 | 
			
		||||
rudimentary Slixmpp plugin to create a :term:`stanza object` for
 | 
			
		||||
interfacting with the :class:`~slixmpp.stanza.iq.Iq` payload.
 | 
			
		||||
 | 
			
		||||
.. seealso::
 | 
			
		||||
 | 
			
		||||
    * :ref:`create-plugin`
 | 
			
		||||
    * :ref:`work-with-stanzas`
 | 
			
		||||
    * :ref:`using-handlers-matchers`
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
The typical way to respond to :class:`~sleekxmpp.stanza.iq.Iq` requests is
 | 
			
		||||
 | 
			
		||||
The typical way to respond to :class:`~slixmpp.stanza.iq.Iq` requests is
 | 
			
		||||
to register stream handlers. As an example, suppose we create a stanza class
 | 
			
		||||
named ``CustomXEP`` which uses the XML element ``<query xmlns="custom-xep" />``,
 | 
			
		||||
and has a :attr:`~sleekxmpp.xmlstream.stanzabase.ElementBase.plugin_attrib` value
 | 
			
		||||
and has a :attr:`~slixmpp.xmlstream.stanzabase.ElementBase.plugin_attrib` value
 | 
			
		||||
of ``custom_xep``.
 | 
			
		||||
 | 
			
		||||
There are two types of incoming :class:`~sleekxmpp.stanza.iq.Iq` requests:
 | 
			
		||||
There are two types of incoming :class:`~slixmpp.stanza.iq.Iq` requests:
 | 
			
		||||
``get`` and ``set``. You can register a handler that will accept both and then
 | 
			
		||||
filter by type as needed, as so:
 | 
			
		||||
 | 
			
		||||
@@ -167,7 +167,7 @@ filter by type as needed, as so:
 | 
			
		||||
 | 
			
		||||
If you want to filter out query types beforehand, you can adjust the matching
 | 
			
		||||
filter by using ``@type=get`` or ``@type=set`` if you are using the recommended
 | 
			
		||||
:class:`~sleekxmpp.xmlstream.matcher.stanzapath.StanzaPath` matcher.
 | 
			
		||||
:class:`~slixmpp.xmlstream.matcher.stanzapath.StanzaPath` matcher.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,21 +7,13 @@ Mulit-User Chat (MUC) Bot
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    If you have any issues working through this quickstart guide
 | 
			
		||||
    or the other tutorials here, please either send a message to the
 | 
			
		||||
    `mailing list <http://groups.google.com/group/sleekxmpp-discussion>`_
 | 
			
		||||
    or join the chat room at `sleek@conference.jabber.org
 | 
			
		||||
    <xmpp:sleek@conference.jabber.org?join>`_.
 | 
			
		||||
    join the chat room at `slixmpp@muc.poez.io
 | 
			
		||||
    <xmpp:slixmpp@muc.poez.io?join>`_.
 | 
			
		||||
 | 
			
		||||
If you have not yet installed SleekXMPP, do so now by either checking out a version
 | 
			
		||||
from `Github <http://github.com/fritzy/SleekXMPP>`_, or installing it using ``pip``
 | 
			
		||||
or ``easy_install``.
 | 
			
		||||
If you have not yet installed Slixmpp, do so now by either checking out a version
 | 
			
		||||
from `Git <http://git.poez.io/slixmpp>`_.
 | 
			
		||||
 | 
			
		||||
.. code-block:: sh
 | 
			
		||||
 | 
			
		||||
    pip install sleekxmpp  # Or: easy_install sleekxmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Now that you've got the basic gist of using SleekXMPP by following the
 | 
			
		||||
Now that you've got the basic gist of using Slixmpp by following the
 | 
			
		||||
echobot example (:ref:`echobot`), we can use one of the bundled plugins
 | 
			
		||||
to create a very popular XMPP starter project: a `Multi-User Chat`_
 | 
			
		||||
(MUC) bot. Our bot will login to an XMPP server, join an MUC chat room
 | 
			
		||||
@@ -36,7 +28,7 @@ Joining The Room
 | 
			
		||||
 | 
			
		||||
As usual, our code will be based on the pattern explained in :ref:`echobot`.
 | 
			
		||||
To start, we create an ``MUCBot`` class based on
 | 
			
		||||
:class:`ClientXMPP <sleekxmpp.clientxmpp.ClientXMPP>` and which accepts
 | 
			
		||||
:class:`ClientXMPP <slixmpp.clientxmpp.ClientXMPP>` and which accepts
 | 
			
		||||
parameters for the JID of the MUC room to join, and the nick that the
 | 
			
		||||
bot will use inside the chat room.  We also register an
 | 
			
		||||
:term:`event handler` for the :term:`session_start` event.
 | 
			
		||||
@@ -44,12 +36,12 @@ bot will use inside the chat room.  We also register an
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import sleekxmpp
 | 
			
		||||
    import slixmpp
 | 
			
		||||
 | 
			
		||||
    class MUCBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
    class MUCBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
        def __init__(self, jid, password, room, nick):
 | 
			
		||||
            sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
            slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
            self.room = room
 | 
			
		||||
            self.nick = nick
 | 
			
		||||
@@ -81,7 +73,7 @@ the roster. Next, we want to join the group chat, so we call the
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    The :attr:`plugin <sleekxmpp.basexmpp.BaseXMPP.plugin>` attribute is
 | 
			
		||||
    The :attr:`plugin <slixmpp.basexmpp.BaseXMPP.plugin>` attribute is
 | 
			
		||||
    dictionary that maps to instances of plugins that we have previously
 | 
			
		||||
    registered, by their names.
 | 
			
		||||
 | 
			
		||||
@@ -115,7 +107,7 @@ event inside the bot's ``__init__`` function.
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, room, nick):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.room = room
 | 
			
		||||
        self.nick = nick
 | 
			
		||||
@@ -159,7 +151,7 @@ event so it's a good idea to register an event handler for it.
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, room, nick):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.room = room
 | 
			
		||||
        self.nick = nick
 | 
			
		||||
 
 | 
			
		||||
@@ -5,19 +5,17 @@ Enable HTTP Proxy Support
 | 
			
		||||
=========================
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    If you have any issues working through this quickstart guide
 | 
			
		||||
    or the other tutorials here, please either send a message to the
 | 
			
		||||
    `mailing list <http://groups.google.com/group/sleekxmpp-discussion>`_
 | 
			
		||||
    or join the chat room at `sleek@conference.jabber.org
 | 
			
		||||
    <xmpp:sleek@conference.jabber.org?join>`_.
 | 
			
		||||
    join the chat room at `slixmpp@muc.poez.io
 | 
			
		||||
    <xmpp:slixmpp@muc.poez.io?join>`_.
 | 
			
		||||
 | 
			
		||||
In some instances, you may wish to route XMPP traffic through
 | 
			
		||||
an HTTP proxy, probably to get around restrictive firewalls.
 | 
			
		||||
SleekXMPP provides support for basic HTTP proxying with DIGEST
 | 
			
		||||
Slixmpp provides support for basic HTTP proxying with DIGEST
 | 
			
		||||
authentication.
 | 
			
		||||
 | 
			
		||||
Enabling proxy support is done in two steps. The first is to instruct SleekXMPP
 | 
			
		||||
Enabling proxy support is done in two steps. The first is to instruct Slixmpp
 | 
			
		||||
to use a proxy, and the second is to configure the proxy details:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 
 | 
			
		||||
@@ -2,29 +2,27 @@ Sign in, Send a Message, and Disconnect
 | 
			
		||||
=======================================
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
    
 | 
			
		||||
    If you have any issues working through this quickstart guide
 | 
			
		||||
    or the other tutorials here, please either send a message to the
 | 
			
		||||
    `mailing list <http://groups.google.com/group/sleekxmpp-discussion>`_
 | 
			
		||||
    or join the chat room at `sleek@conference.jabber.org
 | 
			
		||||
    <xmpp:sleek@conference.jabber.org?join>`_.
 | 
			
		||||
 | 
			
		||||
A common use case for SleekXMPP is to send one-off messages from
 | 
			
		||||
time to time. For example, one use case could be sending out a notice when 
 | 
			
		||||
    If you have any issues working through this quickstart guide
 | 
			
		||||
    join the chat room at `slixmpp@muc.poez.io
 | 
			
		||||
    <xmpp:slixmpp@muc.poez.io?join>`_.
 | 
			
		||||
 | 
			
		||||
A common use case for Slixmpp is to send one-off messages from
 | 
			
		||||
time to time. For example, one use case could be sending out a notice when
 | 
			
		||||
a shell script finishes a task.
 | 
			
		||||
 | 
			
		||||
We will create our one-shot bot based on the pattern explained in :ref:`echobot`. To
 | 
			
		||||
start, we create a client class based on :class:`ClientXMPP <sleekxmpp.clientxmpp.ClientXMPP>` and
 | 
			
		||||
start, we create a client class based on :class:`ClientXMPP <slixmpp.clientxmpp.ClientXMPP>` and
 | 
			
		||||
register a handler for the :term:`session_start` event. We will also accept parameters
 | 
			
		||||
for the JID that will receive our message, and the string content of the message.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import sleekxmpp
 | 
			
		||||
    import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    class SendMsgBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
        
 | 
			
		||||
    class SendMsgBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
        def __init__(self, jid, password, recipient, msg):
 | 
			
		||||
            super(SendMsgBot, self).__init__(jid, password)
 | 
			
		||||
 | 
			
		||||
@@ -38,7 +36,7 @@ for the JID that will receive our message, and the string content of the message
 | 
			
		||||
            self.get_roster()
 | 
			
		||||
 | 
			
		||||
Note that as in :ref:`echobot`, we need to include send an initial presence and request
 | 
			
		||||
the roster. Next, we want to send our message, and to do that we will use :meth:`send_message <sleekxmpp.basexmpp.BaseXMPP.send_message>`.
 | 
			
		||||
the roster. Next, we want to send our message, and to do that we will use :meth:`send_message <slixmpp.basexmpp.BaseXMPP.send_message>`.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
@@ -48,12 +46,12 @@ the roster. Next, we want to send our message, and to do that we will use :meth:
 | 
			
		||||
 | 
			
		||||
        self.send_message(mto=self.recipient, mbody=self.msg)
 | 
			
		||||
 | 
			
		||||
Finally, we need to disconnect the client using :meth:`disconnect <sleekxmpp.xmlstream.XMLStream.disconnect>`.
 | 
			
		||||
Finally, we need to disconnect the client using :meth:`disconnect <slixmpp.xmlstream.XMLStream.disconnect>`.
 | 
			
		||||
Now, sent stanzas are placed in a queue to pass them to the send thread. If we were to call
 | 
			
		||||
:meth:`disconnect <sleekxmpp.xmlstream.XMLStream.disconnect>` without any parameters, then it is possible
 | 
			
		||||
:meth:`disconnect <slixmpp.xmlstream.XMLStream.disconnect>` without any parameters, then it is possible
 | 
			
		||||
for the client to disconnect before the send queue is processed and the message is actually
 | 
			
		||||
sent on the wire. To ensure that our message is processed, we use 
 | 
			
		||||
:meth:`disconnect(wait=True) <sleekxmpp.xmlstream.XMLStream.disconnect>`.
 | 
			
		||||
sent on the wire. To ensure that our message is processed, we use
 | 
			
		||||
:meth:`disconnect(wait=True) <slixmpp.xmlstream.XMLStream.disconnect>`.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
@@ -68,7 +66,7 @@ sent on the wire. To ensure that our message is processed, we use
 | 
			
		||||
.. warning::
 | 
			
		||||
 | 
			
		||||
    If you happen to be adding stanzas to the send queue faster than the send thread
 | 
			
		||||
    can process them, then :meth:`disconnect(wait=True) <sleekxmpp.xmlstream.XMLStream.disconnect>`
 | 
			
		||||
    can process them, then :meth:`disconnect(wait=True) <slixmpp.xmlstream.XMLStream.disconnect>`
 | 
			
		||||
    will block and not disconnect.
 | 
			
		||||
 | 
			
		||||
Final Product
 | 
			
		||||
 
 | 
			
		||||
@@ -9,21 +9,20 @@ Glossary
 | 
			
		||||
    stream handler
 | 
			
		||||
        A callback function that accepts stanza objects pulled directly
 | 
			
		||||
        from the XML stream. A stream handler is encapsulated in a
 | 
			
		||||
        object that includes a :term:`Matcher` object, and which provides
 | 
			
		||||
        additional semantics. For example, the ``Waiter`` handler wrapper
 | 
			
		||||
        blocks thread execution until a matching stanza is received.
 | 
			
		||||
        object that includes a :class:`Matcher <.MatcherBase>` object, and
 | 
			
		||||
        which provides additional semantics. For example, the
 | 
			
		||||
        :class:`.Waiter` handler wrapper blocks thread execution until a
 | 
			
		||||
        matching stanza is received.
 | 
			
		||||
 | 
			
		||||
    event handler
 | 
			
		||||
        A callback function that responds to events raised by
 | 
			
		||||
        ``XMLStream.event``. An event handler may be marked as
 | 
			
		||||
        threaded, allowing it to execute outside of the main processing
 | 
			
		||||
        loop.
 | 
			
		||||
        :meth:`.XMLStream.event`.
 | 
			
		||||
 | 
			
		||||
    stanza object
 | 
			
		||||
        Informally may refer both to classes which extend ``ElementBase``
 | 
			
		||||
        or ``StanzaBase``, and to objects of such classes.
 | 
			
		||||
        Informally may refer both to classes which extend :class:`.ElementBase`
 | 
			
		||||
        or :class:`.StanzaBase`, and to objects of such classes.
 | 
			
		||||
 | 
			
		||||
        A stanza object is a wrapper for an XML object which exposes ``dict``
 | 
			
		||||
        A stanza object is a wrapper for an XML object which exposes :class:`dict`
 | 
			
		||||
        like interfaces which may be assigned to, read from, or deleted.
 | 
			
		||||
 | 
			
		||||
    stanza plugin
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ Working with service discovery is about creating and querying these nodes.
 | 
			
		||||
According to XEP-0030, a node may contain three types of information:
 | 
			
		||||
identities, features, and items. (Further, extensible, information types are
 | 
			
		||||
defined in `XEP-0128 <http://xmpp.org/extensions/xep-0128.html>`_, but they are
 | 
			
		||||
not yet implemented by SleekXMPP.) SleekXMPP provides methods to configure each
 | 
			
		||||
not yet implemented by Slixmpp.) Slixmpp provides methods to configure each
 | 
			
		||||
of these node attributes.
 | 
			
		||||
 | 
			
		||||
Configuring Service Discovery
 | 
			
		||||
@@ -119,7 +119,7 @@ the same order as expected using positional arguments.
 | 
			
		||||
 | 
			
		||||
    xmpp['xep_0030'].add_identity(category='client',
 | 
			
		||||
                                  itype='bot',
 | 
			
		||||
                                  name='Sleek',
 | 
			
		||||
                                  name='Slixmpp',
 | 
			
		||||
                                  node='foo',
 | 
			
		||||
                                  jid=xmpp.boundjid.full,
 | 
			
		||||
                                  lang='no')
 | 
			
		||||
@@ -159,7 +159,7 @@ item itself, and the JID and node that will own the item.
 | 
			
		||||
.. note::
 | 
			
		||||
 | 
			
		||||
    In this case, the owning JID and node are provided with the
 | 
			
		||||
    parameters ``ijid`` and ``node``. 
 | 
			
		||||
    parameters ``ijid`` and ``node``.
 | 
			
		||||
 | 
			
		||||
Peforming Disco Queries
 | 
			
		||||
-----------------------
 | 
			
		||||
@@ -197,5 +197,5 @@ a full Iq stanza.
 | 
			
		||||
 | 
			
		||||
    info = self['xep_0030'].get_info(node='foo', local=True)
 | 
			
		||||
    items = self['xep_0030'].get_items(jid='somejid@mycomponent.example.com',
 | 
			
		||||
                                       node='bar', 
 | 
			
		||||
                                       node='bar',
 | 
			
		||||
                                       local=True)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										112
									
								
								docs/index.rst
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								docs/index.rst
									
									
									
									
									
								
							@@ -1,49 +1,36 @@
 | 
			
		||||
SleekXMPP
 | 
			
		||||
Slixmpp
 | 
			
		||||
#########
 | 
			
		||||
 | 
			
		||||
.. sidebar:: Get the Code
 | 
			
		||||
 | 
			
		||||
    .. code-block:: sh
 | 
			
		||||
    The latest source code for Slixmpp may be found on the `Git repo
 | 
			
		||||
    <http://git.poez.io/slixmpp>`_. ::
 | 
			
		||||
 | 
			
		||||
        pip install sleekxmpp
 | 
			
		||||
        git clone git://git.poez.io/slixmpp
 | 
			
		||||
 | 
			
		||||
    The latest source code for SleekXMPP may be found on `Github
 | 
			
		||||
    <http://github.com/fritzy/SleekXMPP>`_. Releases can be found in the
 | 
			
		||||
    ``master`` branch, while the latest development version is in the
 | 
			
		||||
    ``develop`` branch.
 | 
			
		||||
 | 
			
		||||
    **Latest Stable Release**
 | 
			
		||||
        - `1.0 <http://github.com/fritzy/SleekXMPP/zipball/1.0>`_
 | 
			
		||||
 | 
			
		||||
    **Develop Releases**
 | 
			
		||||
        - `Latest Develop Version <http://github.com/fritzy/SleekXMPP/zipball/develop>`_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    A mailing list and XMPP chat room are available for discussing and getting
 | 
			
		||||
    help with SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    **Mailing List**
 | 
			
		||||
        `SleekXMPP Discussion on Google Groups <http://groups.google.com/group/sleekxmpp-discussion>`_
 | 
			
		||||
    An XMPP chat room is available for discussing and getting help with slixmpp.
 | 
			
		||||
 | 
			
		||||
    **Chat**
 | 
			
		||||
        `sleek@conference.jabber.org <xmpp:sleek@conference.jabber.org?join>`_
 | 
			
		||||
        `slixmpp@muc.poez.io <xmpp:slixmpp@muc.poez.io?join>`_
 | 
			
		||||
 | 
			
		||||
    **Reporting bugs**
 | 
			
		||||
        You can report bugs at http://dev.louiz.org/projects/slixmpp/issues.
 | 
			
		||||
 | 
			
		||||
SleekXMPP is an :ref:`MIT licensed <license>` XMPP library for Python 2.6/3.1+,
 | 
			
		||||
and is featured in examples in
 | 
			
		||||
`XMPP: The Definitive Guide <http://oreilly.com/catalog/9780596521271>`_ 
 | 
			
		||||
by Kevin Smith, Remko Tronçon, and Peter Saint-Andre. If you've arrived
 | 
			
		||||
here from reading the Definitive Guide, please see the notes on updating
 | 
			
		||||
the examples to the latest version of SleekXMPP.
 | 
			
		||||
.. note::
 | 
			
		||||
    slixmpp is a friendly fork of `SleekXMPP <https://github.com/fritzy/SleekXMPP>`_
 | 
			
		||||
    which goal is to use asyncio instead of threads to handle networking. See
 | 
			
		||||
    :ref:`differences`.
 | 
			
		||||
 | 
			
		||||
SleekXMPP's design goals and philosphy are:
 | 
			
		||||
Slixmpp is an :ref:`MIT licensed <license>` XMPP library for Python 3.4+,
 | 
			
		||||
 | 
			
		||||
Slixmpp's design goals and philosphy are:
 | 
			
		||||
 | 
			
		||||
**Low number of dependencies**
 | 
			
		||||
    Installing and using SleekXMPP should be as simple as possible, without
 | 
			
		||||
    Installing and using Slixmpp should be as simple as possible, without
 | 
			
		||||
    having to deal with long dependency chains.
 | 
			
		||||
 | 
			
		||||
    As part of reducing the number of dependencies, some third party
 | 
			
		||||
    modules are included with SleekXMPP in the ``thirdparty`` directory.
 | 
			
		||||
    modules are included with Slixmpp in the ``thirdparty`` directory.
 | 
			
		||||
    Imports from this module first try to import an existing installed
 | 
			
		||||
    version before loading the packaged version, when possible.
 | 
			
		||||
 | 
			
		||||
@@ -55,19 +42,20 @@ SleekXMPP's design goals and philosphy are:
 | 
			
		||||
    XEPs.
 | 
			
		||||
 | 
			
		||||
**Rewarding to work with**
 | 
			
		||||
    As much as possible, SleekXMPP should allow things to "just work" using
 | 
			
		||||
    As much as possible, Slixmpp should allow things to "just work" using
 | 
			
		||||
    sensible defaults and appropriate abstractions. XML can be ugly to work
 | 
			
		||||
    with, but it doesn't have to be that way.
 | 
			
		||||
 | 
			
		||||
Here's your first SleekXMPP Bot:
 | 
			
		||||
 | 
			
		||||
Here's your first Slixmpp Bot:
 | 
			
		||||
--------------------------------
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import asyncio
 | 
			
		||||
    import logging
 | 
			
		||||
 | 
			
		||||
    from sleekxmpp import ClientXMPP
 | 
			
		||||
    from sleekxmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
    from slixmpp import ClientXMPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    class EchoBot(ClientXMPP):
 | 
			
		||||
@@ -85,27 +73,13 @@ Here's your first SleekXMPP Bot:
 | 
			
		||||
            # Here's how to access plugins once you've registered them:
 | 
			
		||||
            # self['xep_0030'].add_feature('echo_demo')
 | 
			
		||||
 | 
			
		||||
            # If you are working with an OpenFire server, you will
 | 
			
		||||
            # need to use a different SSL version:
 | 
			
		||||
            # import ssl
 | 
			
		||||
            # self.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
        def session_start(self, event):
 | 
			
		||||
            self.send_presence()
 | 
			
		||||
            self.get_roster()
 | 
			
		||||
 | 
			
		||||
            # Most get_*/set_* methods from plugins use Iq stanzas, which
 | 
			
		||||
            # can generate IqError and IqTimeout exceptions
 | 
			
		||||
            #
 | 
			
		||||
            # try:
 | 
			
		||||
            #     self.get_roster()
 | 
			
		||||
            # except IqError as err:
 | 
			
		||||
            #     logging.error('There was an error getting the roster')
 | 
			
		||||
            #     logging.error(err.iq['error']['condition'])
 | 
			
		||||
            #     self.disconnect()
 | 
			
		||||
            # except IqTimeout:
 | 
			
		||||
            #     logging.error('Server is taking too long to respond')
 | 
			
		||||
            #     self.disconnect()
 | 
			
		||||
            # are sent asynchronously. You can almost always provide a
 | 
			
		||||
            # callback that will be executed when the reply is received.
 | 
			
		||||
 | 
			
		||||
        def message(self, msg):
 | 
			
		||||
            if msg['type'] in ('chat', 'normal'):
 | 
			
		||||
@@ -113,7 +87,7 @@ Here's your first SleekXMPP Bot:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if __name__ == '__main__':
 | 
			
		||||
        # Ideally use optparse or argparse to get JID, 
 | 
			
		||||
        # Ideally use optparse or argparse to get JID,
 | 
			
		||||
        # password, and log level.
 | 
			
		||||
 | 
			
		||||
        logging.basicConfig(level=logging.DEBUG,
 | 
			
		||||
@@ -121,15 +95,24 @@ Here's your first SleekXMPP Bot:
 | 
			
		||||
 | 
			
		||||
        xmpp = EchoBot('somejid@example.com', 'use_getpass')
 | 
			
		||||
        xmpp.connect()
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        xmpp.process()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
To read if you come from SleekXMPP
 | 
			
		||||
----------------------------------
 | 
			
		||||
 | 
			
		||||
.. toctree::
 | 
			
		||||
    :maxdepth: 1
 | 
			
		||||
 | 
			
		||||
    differences
 | 
			
		||||
    using_asyncio
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Getting Started (with Examples)
 | 
			
		||||
-------------------------------
 | 
			
		||||
.. toctree::
 | 
			
		||||
    :maxdepth: 1
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    getting_started/echobot
 | 
			
		||||
    getting_started/sendlogout
 | 
			
		||||
    getting_started/component
 | 
			
		||||
@@ -144,8 +127,7 @@ Tutorials, FAQs, and How To Guides
 | 
			
		||||
----------------------------------
 | 
			
		||||
.. toctree::
 | 
			
		||||
    :maxdepth: 1
 | 
			
		||||
   
 | 
			
		||||
    faq
 | 
			
		||||
 | 
			
		||||
    xeps
 | 
			
		||||
    xmpp_tdg
 | 
			
		||||
    howto/stanzas
 | 
			
		||||
@@ -156,12 +138,12 @@ Tutorials, FAQs, and How To Guides
 | 
			
		||||
 | 
			
		||||
Plugin Guides
 | 
			
		||||
~~~~~~~~~~~~~
 | 
			
		||||
.. toctree:: 
 | 
			
		||||
.. toctree::
 | 
			
		||||
    :maxdepth: 1
 | 
			
		||||
 | 
			
		||||
    guide_xep_0030
 | 
			
		||||
 | 
			
		||||
SleekXMPP Architecture and Design
 | 
			
		||||
Slixmpp Architecture and Design
 | 
			
		||||
---------------------------------
 | 
			
		||||
.. toctree::
 | 
			
		||||
    :maxdepth: 3
 | 
			
		||||
@@ -173,7 +155,7 @@ API Reference
 | 
			
		||||
-------------
 | 
			
		||||
.. toctree::
 | 
			
		||||
    :maxdepth: 2
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    event_index
 | 
			
		||||
    api/clientxmpp
 | 
			
		||||
    api/componentxmpp
 | 
			
		||||
@@ -184,9 +166,7 @@ API Reference
 | 
			
		||||
    api/xmlstream/handler
 | 
			
		||||
    api/xmlstream/matcher
 | 
			
		||||
    api/xmlstream/xmlstream
 | 
			
		||||
    api/xmlstream/scheduler
 | 
			
		||||
    api/xmlstream/tostring
 | 
			
		||||
    api/xmlstream/filesocket
 | 
			
		||||
 | 
			
		||||
Core Stanzas
 | 
			
		||||
~~~~~~~~~~~~
 | 
			
		||||
@@ -197,8 +177,6 @@ Core Stanzas
 | 
			
		||||
    api/stanza/message
 | 
			
		||||
    api/stanza/presence
 | 
			
		||||
    api/stanza/iq
 | 
			
		||||
    api/stanza/error
 | 
			
		||||
    api/stanza/stream_error
 | 
			
		||||
 | 
			
		||||
Plugins
 | 
			
		||||
~~~~~~~
 | 
			
		||||
@@ -220,8 +198,14 @@ Additional Info
 | 
			
		||||
* :ref:`modindex`
 | 
			
		||||
* :ref:`search`
 | 
			
		||||
 | 
			
		||||
Credits
 | 
			
		||||
-------
 | 
			
		||||
SleekXMPP Credits
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
    Those people made SleekXMPP, so you should not bother them if
 | 
			
		||||
    you have an issue with slixmpp. But it’s still fair to credit
 | 
			
		||||
    them for their work.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
**Main Author:** `Nathan Fritz <http://andyet.net/team/fritzy>`_
 | 
			
		||||
     `fritzy@netflint.net <xmpp:fritzy@netflint.net?message>`_,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
.. _license: 
 | 
			
		||||
.. _license:
 | 
			
		||||
 | 
			
		||||
License (MIT)
 | 
			
		||||
=============
 | 
			
		||||
 
 | 
			
		||||
@@ -95,9 +95,9 @@ if "%1" == "qthelp" (
 | 
			
		||||
	echo.
 | 
			
		||||
	echo.Build finished; now you can run "qcollectiongenerator" with the ^
 | 
			
		||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
 | 
			
		||||
	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\SleekXMPP.qhcp
 | 
			
		||||
	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Slixmpp.qhcp
 | 
			
		||||
	echo.To view the help file:
 | 
			
		||||
	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\SleekXMPP.ghc
 | 
			
		||||
	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Slixmpp.ghc
 | 
			
		||||
	goto end
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										148
									
								
								docs/using_asyncio.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								docs/using_asyncio.rst
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,148 @@
 | 
			
		||||
.. _using_asyncio:
 | 
			
		||||
 | 
			
		||||
=============
 | 
			
		||||
Using asyncio
 | 
			
		||||
=============
 | 
			
		||||
 | 
			
		||||
Block on IQ sending
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
:meth:`.Iq.send` now returns a :class:`~.Future` so you can easily block with:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    result = yield from iq.send()
 | 
			
		||||
 | 
			
		||||
.. warning::
 | 
			
		||||
 | 
			
		||||
    If the reply is an IQ with an ``error`` type, this will raise an
 | 
			
		||||
    :class:`.IqError`, and if it timeouts, it will raise an
 | 
			
		||||
    :class:`.IqTimeout`. Don't forget to catch it.
 | 
			
		||||
 | 
			
		||||
You can still use callbacks instead.
 | 
			
		||||
 | 
			
		||||
XEP plugin integration
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
The same changes from the SleekXMPP API apply, so you can do:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    iq_info = yield from self.xmpp['xep_0030'].get_info(jid)
 | 
			
		||||
 | 
			
		||||
But the following will only return a Future:
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    iq_info = self.xmpp['xep_0030'].get_info(jid)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Callbacks, Event Handlers, and Stream Handlers
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
IQ callbacks and :term:`Event Handlers <event handler>` can be coroutine
 | 
			
		||||
functions; in this case, they will be scheduled in the event loop using
 | 
			
		||||
:meth:`.asyncio.async` and not ran immediately.
 | 
			
		||||
 | 
			
		||||
A :class:`.CoroutineCallback` class has been added as well for
 | 
			
		||||
:term:`Stream Handlers <stream handler>`, which will use
 | 
			
		||||
:meth:`.asyncio.async` to schedule the callback.
 | 
			
		||||
 | 
			
		||||
Running the event loop
 | 
			
		||||
~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
:meth:`.XMLStream.process` is only a thin wrapper on top of
 | 
			
		||||
``loop.run_forever()`` (if ``timeout`` is provided then it will
 | 
			
		||||
only run for this amount of time, and if ``forever`` is False it will
 | 
			
		||||
run until disconnection).
 | 
			
		||||
 | 
			
		||||
Therefore you can handle the event loop in any way you like
 | 
			
		||||
instead of using ``process()``.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Examples
 | 
			
		||||
~~~~~~~~
 | 
			
		||||
 | 
			
		||||
Blocking until the session is established
 | 
			
		||||
-----------------------------------------
 | 
			
		||||
 | 
			
		||||
This code blocks until the XMPP session is fully established, which
 | 
			
		||||
can be useful to make sure external events aren’t triggering XMPP
 | 
			
		||||
callbacks while everything is not ready.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import asyncio, slixmpp
 | 
			
		||||
 | 
			
		||||
    client = slixmpp.ClientXMPP('jid@example', 'password')
 | 
			
		||||
    client.connected_event = asyncio.Event()
 | 
			
		||||
    callback = lambda _: client.connected_event.set()
 | 
			
		||||
    client.add_event_handler('session_start', callback)
 | 
			
		||||
    client.connect()
 | 
			
		||||
    loop.run_until_complete(event.wait())
 | 
			
		||||
    # do some other stuff before running the event loop, e.g.
 | 
			
		||||
    # loop.run_until_complete(httpserver.init())
 | 
			
		||||
    client.process()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Use with other asyncio-based libraries
 | 
			
		||||
--------------------------------------
 | 
			
		||||
 | 
			
		||||
This code interfaces with aiohttp to retrieve two pages asynchronously
 | 
			
		||||
when the session is established, and then send the HTML content inside
 | 
			
		||||
a simple <message>.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import asyncio, aiohttp, slixmpp
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def get_pythonorg(event):
 | 
			
		||||
        req = yield from aiohttp.request('get', 'http://www.python.org')
 | 
			
		||||
        text = yield from req.text
 | 
			
		||||
        client.send_message(mto='jid2@example', mbody=text)
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def get_asyncioorg(event):
 | 
			
		||||
        req = yield from aiohttp.request('get', 'http://www.asyncio.org')
 | 
			
		||||
        text = yield from req.text
 | 
			
		||||
        client.send_message(mto='jid3@example', mbody=text)
 | 
			
		||||
 | 
			
		||||
    client = slixmpp.ClientXMPP('jid@example', 'password')
 | 
			
		||||
    client.add_event_handler('session_start', get_pythonorg)
 | 
			
		||||
    client.add_event_handler('session_start', get_asyncioorg)
 | 
			
		||||
    client.connect()
 | 
			
		||||
    client.process()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Blocking Iq
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
This client checks (via XEP-0092) the software used by every entity it
 | 
			
		||||
receives a message from. After this, it sends a message to a specific
 | 
			
		||||
JID indicating its findings.
 | 
			
		||||
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    import asyncio, slixmpp
 | 
			
		||||
 | 
			
		||||
    class ExampleClient(slixmpp.ClientXMPP):
 | 
			
		||||
        def __init__(self, *args, **kwargs):
 | 
			
		||||
            slixmpp.ClientXMPP.__init__(self, *args, **kwargs)
 | 
			
		||||
            self.register_plugin('xep_0092')
 | 
			
		||||
            self.add_event_handler('message', self.on_message)
 | 
			
		||||
 | 
			
		||||
        @asyncio.coroutine
 | 
			
		||||
        def on_message(self, event):
 | 
			
		||||
            # You should probably handle IqError and IqTimeout exceptions here
 | 
			
		||||
            # but this is an example.
 | 
			
		||||
            version = yield from self['xep_0092'].get_version(message['from'])
 | 
			
		||||
            text = "%s sent me a message, he runs %s" % (message['from'],
 | 
			
		||||
                                                         version['software_version']['name'])
 | 
			
		||||
            self.send_message(mto='master@example.tld', mbody=text)
 | 
			
		||||
 | 
			
		||||
    client = ExampleClient('jid@example', 'password')
 | 
			
		||||
    client.connect()
 | 
			
		||||
    client.process()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -4,9 +4,9 @@ Supported XEPS
 | 
			
		||||
======= ============================= ================
 | 
			
		||||
XEP     Description                   Notes
 | 
			
		||||
======= ============================= ================
 | 
			
		||||
`0004`_ Data forms                   
 | 
			
		||||
`0009`_ Jabber RPC                   
 | 
			
		||||
`0012`_ Last Activity             
 | 
			
		||||
`0004`_ Data forms
 | 
			
		||||
`0009`_ Jabber RPC
 | 
			
		||||
`0012`_ Last Activity
 | 
			
		||||
`0030`_ Service Discovery
 | 
			
		||||
`0033`_ Extended Stanza Addressing
 | 
			
		||||
`0045`_ Multi-User Chat (MUC)         Client-side only
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,20 @@
 | 
			
		||||
Following *XMPP: The Definitive Guide*
 | 
			
		||||
======================================
 | 
			
		||||
 | 
			
		||||
SleekXMPP was featured in the first edition of the O'Reilly book 
 | 
			
		||||
Slixmpp was featured in the first edition of the O'Reilly book
 | 
			
		||||
`XMPP: The Definitive Guide <http://oreilly.com/catalog/9780596521271/>`_
 | 
			
		||||
by Peter Saint-Andre, Kevin Smith, and Remko Tronçon. The original source code
 | 
			
		||||
for the book's examples can be found at http://github.com/remko/xmpp-tdg. An
 | 
			
		||||
updated version of the source code, maintained to stay current with the latest
 | 
			
		||||
SleekXMPP release, is available at http://github.com/legastero/xmpp-tdg.
 | 
			
		||||
Slixmpp release, is available at http://github.com/legastero/xmpp-tdg.
 | 
			
		||||
 | 
			
		||||
However, since publication, SleekXMPP has advanced from version 0.2.1 to version
 | 
			
		||||
However, since publication, Slixmpp has advanced from version 0.2.1 to version
 | 
			
		||||
1.0 and there have been several major API changes. The most notable is the
 | 
			
		||||
introduction of :term:`stanza objects <stanza object>` which have simplified and
 | 
			
		||||
standardized interactions with the XMPP XML stream.
 | 
			
		||||
 | 
			
		||||
What follows is a walk-through of *The Definitive Guide* highlighting the
 | 
			
		||||
changes needed to make the code examples work with version 1.0 of SleekXMPP.
 | 
			
		||||
changes needed to make the code examples work with version 1.0 of Slixmpp.
 | 
			
		||||
These changes have been kept to a minimum to preserve the correlation with
 | 
			
		||||
the book's explanations, so be aware that some code may not use current best
 | 
			
		||||
practices.
 | 
			
		||||
@@ -36,7 +36,7 @@ Updated Code
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
    def handleIncomingMessage(self, message):
 | 
			
		||||
        self.xmpp.sendMessage(message["from"], message["body"])
 | 
			
		||||
        self.xmpp.send_message(message["from"], message["body"])
 | 
			
		||||
 | 
			
		||||
`View full source <http://github.com/legastero/xmpp-tdg/blob/master/code/EchoBot/EchoBot.py>`_ |
 | 
			
		||||
`View original code <http://github.com/remko/xmpp-tdg/blob/master/code/EchoBot/EchoBot.py>`_
 | 
			
		||||
@@ -47,7 +47,7 @@ Example 14-1. (Page 215)
 | 
			
		||||
**CheshiR IM bot implementation.**
 | 
			
		||||
 | 
			
		||||
The main event handling method in the Bot class is meant to process both message
 | 
			
		||||
events and presence update events. With the new changes in SleekXMPP 1.0,
 | 
			
		||||
events and presence update events. With the new changes in Slixmpp 1.0,
 | 
			
		||||
extracting a CheshiR status "message" from both types of stanzas
 | 
			
		||||
requires accessing different attributes. In the case of a message stanza, the
 | 
			
		||||
``"body"`` attribute would contain the CheshiR message. For a presence event,
 | 
			
		||||
@@ -72,21 +72,21 @@ Updated Code
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
  def handleIncomingXMPPEvent(self, event):
 | 
			
		||||
    msgLocations = {sleekxmpp.stanza.presence.Presence: "status",
 | 
			
		||||
                    sleekxmpp.stanza.message.Message: "body"}
 | 
			
		||||
    msgLocations = {slixmpp.stanza.presence.Presence: "status",
 | 
			
		||||
                    slixmpp.stanza.message.Message: "body"}
 | 
			
		||||
 | 
			
		||||
    message = event[msgLocations[type(event)]]
 | 
			
		||||
    user = self.backend.getUserFromJID(event["from"].jid)
 | 
			
		||||
    if user is not None:
 | 
			
		||||
      self.backend.addMessageFromUser(message, user)
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  def handleMessageAddedToBackend(self, message) :
 | 
			
		||||
    body = message.user + ": " + message.text
 | 
			
		||||
    htmlBody = "<p><a href='%(uri)s'>%(user)s</a>: %(message)s</p>" % {
 | 
			
		||||
      "uri": self.url + "/" + message.user,
 | 
			
		||||
      "user" : message.user, "message" : message.text }
 | 
			
		||||
    for subscriberJID in self.backend.getSubscriberJIDs(message.user) :
 | 
			
		||||
      self.xmpp.sendMessage(subscriberJID, body, mhtml=htmlBody)
 | 
			
		||||
      self.xmpp.send_message(subscriberJID, body, mhtml=htmlBody)
 | 
			
		||||
 | 
			
		||||
`View full source <http://github.com/legastero/xmpp-tdg/blob/master/code/CheshiR/Bot.py>`_ |
 | 
			
		||||
`View original code <http://github.com/remko/xmpp-tdg/blob/master/code/CheshiR/Bot.py>`_
 | 
			
		||||
@@ -102,7 +102,7 @@ Example 14-3. (Page 217)
 | 
			
		||||
 | 
			
		||||
The main difference for the configurable IM bot is the handling for the
 | 
			
		||||
data form in ``handleConfigurationCommand``. The test for equality
 | 
			
		||||
with the string ``"1"`` is no longer required; SleekXMPP converts
 | 
			
		||||
with the string ``"1"`` is no longer required; Slixmpp converts
 | 
			
		||||
boolean data form fields to the values ``True`` and ``False``
 | 
			
		||||
automatically.
 | 
			
		||||
 | 
			
		||||
@@ -145,7 +145,7 @@ Example 14-4. (Page 220)
 | 
			
		||||
 | 
			
		||||
Like several previous examples, a needed change is to replace
 | 
			
		||||
``subscription["from"]`` with ``subscription["from"].jid`` because the
 | 
			
		||||
``BaseXMPP`` method ``makePresence`` requires the JID to be a string.
 | 
			
		||||
``BaseXMPP`` method ``make_presence`` requires the JID to be a string.
 | 
			
		||||
 | 
			
		||||
A correction needs to be made in ``handleXMPPPresenceProbe`` because a line was
 | 
			
		||||
left out of the original implementation; the variable ``user`` is undefined. The
 | 
			
		||||
@@ -154,7 +154,7 @@ JID of the user can be extracted from the presence stanza's ``from`` attribute.
 | 
			
		||||
Since this implementation of CheshiR uses an XMPP component, it must
 | 
			
		||||
include a ``from`` attribute in all messages that it sends. Adding the
 | 
			
		||||
``from`` attribute is done by including ``mfrom=self.xmpp.jid`` in calls to
 | 
			
		||||
``self.xmpp.sendMessage``.
 | 
			
		||||
``self.xmpp.send_message``.
 | 
			
		||||
 | 
			
		||||
Updated Code
 | 
			
		||||
~~~~~~~~~~~~
 | 
			
		||||
@@ -162,19 +162,19 @@ Updated Code
 | 
			
		||||
.. code-block:: python
 | 
			
		||||
 | 
			
		||||
  def handleXMPPPresenceProbe(self, event) :
 | 
			
		||||
    self.xmpp.sendPresence(pto = event["from"])
 | 
			
		||||
    self.xmpp.send_presence(pto = event["from"])
 | 
			
		||||
 | 
			
		||||
  def handleXMPPPresenceSubscription(self, subscription) :
 | 
			
		||||
    if subscription["type"] == "subscribe" :
 | 
			
		||||
      userJID = subscription["from"].jid
 | 
			
		||||
      self.xmpp.sendPresenceSubscription(pto=userJID, ptype="subscribed")
 | 
			
		||||
      self.xmpp.sendPresence(pto = userJID)
 | 
			
		||||
      self.xmpp.sendPresenceSubscription(pto=userJID, ptype="subscribe")
 | 
			
		||||
      self.xmpp.send_presence_subscription(pto=userJID, ptype="subscribed")
 | 
			
		||||
      self.xmpp.send_presence(pto = userJID)
 | 
			
		||||
      self.xmpp.send_presence_subscription(pto=userJID, ptype="subscribe")
 | 
			
		||||
 | 
			
		||||
  def handleMessageAddedToBackend(self, message) :
 | 
			
		||||
    body = message.user + ": " + message.text
 | 
			
		||||
    for subscriberJID in self.backend.getSubscriberJIDs(message.user) :
 | 
			
		||||
      self.xmpp.sendMessage(subscriberJID, body, mfrom=self.xmpp.jid)
 | 
			
		||||
      self.xmpp.send_message(subscriberJID, body, mfrom=self.xmpp.jid)
 | 
			
		||||
 | 
			
		||||
`View full source <http://github.com/legastero/xmpp-tdg/blob/master/code/CheshiR/SimpleComponent.py>`_ |
 | 
			
		||||
`View original code <http://github.com/remko/xmpp-tdg/blob/master/code/CheshiR/SimpleComponent.py>`_
 | 
			
		||||
@@ -192,7 +192,7 @@ After applying the changes from Example 14-4 above, the registrable component
 | 
			
		||||
implementation should work correctly.
 | 
			
		||||
 | 
			
		||||
.. tip::
 | 
			
		||||
    To see how to implement in-band registration as a SleekXMPP plugin,
 | 
			
		||||
    To see how to implement in-band registration as a Slixmpp plugin,
 | 
			
		||||
    see the tutorial :ref:`tutorial-create-plugin`.
 | 
			
		||||
 | 
			
		||||
`View full source <http://github.com/legastero/xmpp-tdg/blob/master/code/CheshiR/RegistrableComponent.py>`_ |
 | 
			
		||||
@@ -203,13 +203,13 @@ Example 14-7. (Page 225)
 | 
			
		||||
**Extended CheshiR IM server component implementation.**
 | 
			
		||||
 | 
			
		||||
.. note::
 | 
			
		||||
    Since the CheshiR examples build on each other, see previous 
 | 
			
		||||
    Since the CheshiR examples build on each other, see previous
 | 
			
		||||
    sections for corrections to code that is not marked as new in the book
 | 
			
		||||
    example.
 | 
			
		||||
 | 
			
		||||
While the final code example can look daunting with all of the changes
 | 
			
		||||
made, it requires very few modifications to work with the latest version of
 | 
			
		||||
SleekXMPP. Most differences are the result of CheshiR's backend functions
 | 
			
		||||
Slixmpp. Most differences are the result of CheshiR's backend functions
 | 
			
		||||
expecting JIDs to be strings so that they can be stripped to bare JIDs. To
 | 
			
		||||
resolve these, use the ``jid`` attribute of the JID objects. Also,
 | 
			
		||||
references to ``"message"`` and ``"jid"`` attributes need to
 | 
			
		||||
@@ -239,11 +239,11 @@ Updated Code
 | 
			
		||||
      userJID = subscription["from"].jid
 | 
			
		||||
      user = self.backend.getUserFromJID(userJID)
 | 
			
		||||
      contactJID = subscription["to"]
 | 
			
		||||
      self.xmpp.sendPresenceSubscription(
 | 
			
		||||
      self.xmpp.send_presence_subscription(
 | 
			
		||||
          pfrom=contactJID, pto=userJID, ptype="subscribed", pnick=user)
 | 
			
		||||
      self.sendPresenceOfContactToUser(contactJID=contactJID, userJID=userJID)
 | 
			
		||||
      if contactJID == self.componentDomain :
 | 
			
		||||
        self.sendAllContactSubscriptionRequestsToUser(userJID)
 | 
			
		||||
 | 
			
		||||
`View full source <http://github.com/legastero/xmpp-tdg/blob/master/code/CheshiR/Component.py>`_ |
 | 
			
		||||
`View original code <http://github.com/remko/xmpp-tdg/blob/master/code/CheshiR/Component.py>`_ 
 | 
			
		||||
`View original code <http://github.com/remko/xmpp-tdg/blob/master/code/CheshiR/Component.py>`_
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										182
									
								
								examples/IoT_TestDevice.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										182
									
								
								examples/IoT_TestDevice.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,182 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Implementation of xeps for Internet of Things
 | 
			
		||||
    http://wiki.xmpp.org/web/Tech_pages/IoT_systems
 | 
			
		||||
    Copyright (C) 2013 Sustainable Innovation, Joachim.lindborg@sust.se
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
 | 
			
		||||
from os.path import basename, join as pjoin
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
from urllib import urlopen
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.plugins.xep_0323.device import Device
 | 
			
		||||
 | 
			
		||||
#from slixmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
 | 
			
		||||
class IoT_TestDevice(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple IoT device that can act as server or client
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        self.add_event_handler("session_start", self.session_start)
 | 
			
		||||
        self.add_event_handler("message", self.message)
 | 
			
		||||
        self.device=None
 | 
			
		||||
        self.releaseMe=False
 | 
			
		||||
        self.beServer=True
 | 
			
		||||
        self.clientJID=None
 | 
			
		||||
 | 
			
		||||
    def datacallback(self,from_jid,result,nodeId=None,timestamp=None,fields=None,error_msg=None):
 | 
			
		||||
        """
 | 
			
		||||
        This method will be called when you ask another IoT device for data with the xep_0323
 | 
			
		||||
        se script below for the registration of the callback
 | 
			
		||||
        """
 | 
			
		||||
        logging.debug("we got data %s from %s",str(result),from_jid)
 | 
			
		||||
 | 
			
		||||
    def beClientOrServer(self,server=True,clientJID=None ):
 | 
			
		||||
        if server:
 | 
			
		||||
            self.beServer=True
 | 
			
		||||
            self.clientJID=None
 | 
			
		||||
        else:
 | 
			
		||||
            self.beServer=False
 | 
			
		||||
            self.clientJID=clientJID
 | 
			
		||||
 | 
			
		||||
    def testForRelease(self):
 | 
			
		||||
        # todo thread safe
 | 
			
		||||
        return self.releaseMe
 | 
			
		||||
 | 
			
		||||
    def doReleaseMe(self):
 | 
			
		||||
        # todo thread safe
 | 
			
		||||
        self.releaseMe=True
 | 
			
		||||
 | 
			
		||||
    def addDevice(self, device):
 | 
			
		||||
        self.device=device
 | 
			
		||||
 | 
			
		||||
    def session_start(self, event):
 | 
			
		||||
        self.send_presence()
 | 
			
		||||
        self.get_roster()
 | 
			
		||||
        # tell your preffered friend that you are alive
 | 
			
		||||
        self.send_message(mto='jocke@jabber.sust.se', mbody=self.boundjid.bare +' is now online use xep_323 stanza to talk to me')
 | 
			
		||||
 | 
			
		||||
        if not(self.beServer):
 | 
			
		||||
            session=self['xep_0323'].request_data(self.boundjid.full,self.clientJID,self.datacallback)
 | 
			
		||||
 | 
			
		||||
    def message(self, msg):
 | 
			
		||||
        if msg['type'] in ('chat', 'normal'):
 | 
			
		||||
            logging.debug("got normal chat message" + str(msg))
 | 
			
		||||
            ip=urlopen('http://icanhazip.com').read()
 | 
			
		||||
            msg.reply("Hi I am " + self.boundjid.full + " and I am on IP " + ip).send()
 | 
			
		||||
        else:
 | 
			
		||||
            logging.debug("got unknown message type %s", str(msg['type']))
 | 
			
		||||
 | 
			
		||||
class TheDevice(Device):
 | 
			
		||||
    """
 | 
			
		||||
    This is the actual device object that you will use to get information from your real hardware
 | 
			
		||||
    You will be called in the refresh method when someone is requesting information from you
 | 
			
		||||
    """
 | 
			
		||||
    def __init__(self,nodeId):
 | 
			
		||||
        Device.__init__(self,nodeId)
 | 
			
		||||
        self.counter=0
 | 
			
		||||
 | 
			
		||||
    def refresh(self,fields):
 | 
			
		||||
        """
 | 
			
		||||
        the implementation of the refresh method
 | 
			
		||||
        """
 | 
			
		||||
        self._set_momentary_timestamp(self._get_timestamp())
 | 
			
		||||
        self.counter+=self.counter
 | 
			
		||||
        self._add_field_momentary_data(self, "Temperature", self.counter)
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    #
 | 
			
		||||
    # This script can act both as
 | 
			
		||||
    #   "server" an IoT device that can provide sensorinformation
 | 
			
		||||
    #   python IoT_TestDevice.py -j "serverjid@yourdomain.com" -p "password" -n "TestIoT" --debug
 | 
			
		||||
    #
 | 
			
		||||
    #   "client" an IoT device or other party that would like to get data from another device
 | 
			
		||||
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-t", "--pingto", help="set jid to ping",
 | 
			
		||||
                        action="store", type="string", dest="pingjid",
 | 
			
		||||
                        default=None)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    # IoT test
 | 
			
		||||
    parser.add_argument("-c", "--sensorjid", dest="sensorjid",
 | 
			
		||||
                        help="Another device to call for data on", default=None)
 | 
			
		||||
    parser.add_argument("-n", "--nodeid", dest="nodeid",
 | 
			
		||||
                        help="I am a device get ready to be called", default=None)
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
     # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    xmpp = IoT_TestDevice(args.jid,args.password)
 | 
			
		||||
    xmpp.register_plugin('xep_0030')
 | 
			
		||||
    #xmpp['xep_0030'].add_feature(feature='urn:xmpp:iot:sensordata',
 | 
			
		||||
    #                             node=None,
 | 
			
		||||
    #    jid=None)
 | 
			
		||||
    xmpp.register_plugin('xep_0323')
 | 
			
		||||
    xmpp.register_plugin('xep_0325')
 | 
			
		||||
 | 
			
		||||
    if args.nodeid:
 | 
			
		||||
 | 
			
		||||
        # xmpp['xep_0030'].add_feature(feature='urn:xmpp:sn',
 | 
			
		||||
        # node=args.nodeid,
 | 
			
		||||
        # jid=xmpp.boundjid.full)
 | 
			
		||||
 | 
			
		||||
        myDevice = TheDevice(args.nodeid);
 | 
			
		||||
        # myDevice._add_field(name="Relay", typename="numeric", unit="Bool");
 | 
			
		||||
        myDevice._add_field(name="Temperature", typename="numeric", unit="C");
 | 
			
		||||
        myDevice._set_momentary_timestamp("2013-03-07T16:24:30")
 | 
			
		||||
        myDevice._add_field_momentary_data("Temperature", "23.4", flags={"automaticReadout": "true"});
 | 
			
		||||
 | 
			
		||||
        xmpp['xep_0323'].register_node(nodeId=args.nodeid, device=myDevice, commTimeout=10);
 | 
			
		||||
        xmpp.beClientOrServer(server=True)
 | 
			
		||||
        while not(xmpp.testForRelease()):
 | 
			
		||||
            xmpp.connect()
 | 
			
		||||
            xmpp.process(block=True)
 | 
			
		||||
            logging.debug("lost connection")
 | 
			
		||||
    if args.sensorjid:
 | 
			
		||||
        logging.debug("will try to call another device for data")
 | 
			
		||||
        xmpp.beClientOrServer(server=False,clientJID=args.sensorjid)
 | 
			
		||||
        xmpp.connect()
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        logging.debug("ready ending")
 | 
			
		||||
 | 
			
		||||
    else:
 | 
			
		||||
       print("noopp didn't happen")
 | 
			
		||||
 | 
			
		||||
@@ -1,41 +1,30 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CommandBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class CommandBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that provides a basic
 | 
			
		||||
    A simple Slixmpp bot that provides a basic
 | 
			
		||||
    adhoc command.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
@@ -143,62 +132,42 @@ class CommandBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the CommandBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = CommandBot(opts.jid, opts.password)
 | 
			
		||||
    xmpp = CommandBot(args.jid, args.password)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0050') # Adhoc Commands
 | 
			
		||||
    xmpp.register_plugin('xep_0199', {'keepalive': True, 'frequency':15})
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,41 +1,30 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CommandUserBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class CommandUserBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that uses the adhoc command
 | 
			
		||||
    A simple Slixmpp bot that uses the adhoc command
 | 
			
		||||
    provided by the adhoc_provider.py example.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, other, greeting):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.command_provider = other
 | 
			
		||||
        self.greeting = greeting
 | 
			
		||||
@@ -142,69 +131,49 @@ class CommandUserBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("-o", "--other", dest="other",
 | 
			
		||||
                    help="JID providing commands")
 | 
			
		||||
    optp.add_option("-g", "--greeting", dest="greeting",
 | 
			
		||||
                    help="Greeting")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-o", "--other", dest="other",
 | 
			
		||||
                        help="JID providing commands")
 | 
			
		||||
    parser.add_argument("-g", "--greeting", dest="greeting",
 | 
			
		||||
                        help="Greeting")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.other is None:
 | 
			
		||||
        opts.other = raw_input("JID Providing Commands: ")
 | 
			
		||||
    if opts.greeting is None:
 | 
			
		||||
        opts.greeting = raw_input("Greeting: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.other is None:
 | 
			
		||||
        args.other = input("JID Providing Commands: ")
 | 
			
		||||
    if args.greeting is None:
 | 
			
		||||
        args.greeting = input("Greeting: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the CommandBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = CommandUserBot(opts.jid, opts.password, opts.other, opts.greeting)
 | 
			
		||||
    xmpp = CommandUserBot(args.jid, args.password, args.other, args.greeting)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0050') # Adhoc Commands
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,41 +1,30 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AdminCommands(sleekxmpp.ClientXMPP):
 | 
			
		||||
class AdminCommands(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that uses admin commands to
 | 
			
		||||
    A simple Slixmpp bot that uses admin commands to
 | 
			
		||||
    add a new user to a server.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, command):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.command = command
 | 
			
		||||
 | 
			
		||||
@@ -81,13 +70,13 @@ class AdminCommands(sleekxmpp.ClientXMPP):
 | 
			
		||||
            for var, field in form['fields'].items():
 | 
			
		||||
                if var != 'FORM_TYPE':
 | 
			
		||||
                    if field['type'] == 'boolean':
 | 
			
		||||
                        answers[var] = raw_input('%s (y/n): ' % field['label'])
 | 
			
		||||
                        answers[var] = input('%s (y/n): ' % field['label'])
 | 
			
		||||
                        if answers[var].lower() in ('1', 'true', 'y', 'yes'):
 | 
			
		||||
                            answers[var] = '1'
 | 
			
		||||
                        else:
 | 
			
		||||
                            answers[var] = '0'
 | 
			
		||||
                    else:
 | 
			
		||||
                        answers[var] = raw_input('%s: ' % field['label'])
 | 
			
		||||
                        answers[var] = input('%s: ' % field['label'])
 | 
			
		||||
                else:
 | 
			
		||||
                    answers['FORM_TYPE'] = field['value']
 | 
			
		||||
            form['type'] = 'submit'
 | 
			
		||||
@@ -116,63 +105,43 @@ class AdminCommands(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("-c", "--command", dest="command",
 | 
			
		||||
                    help="admin command to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-c", "--command", dest="command",
 | 
			
		||||
                        help="admin command to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.command is None:
 | 
			
		||||
        opts.command = raw_input("Admin command: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.command is None:
 | 
			
		||||
        args.command = input("Admin command: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the CommandBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = AdminCommands(opts.jid, opts.password, opts.command)
 | 
			
		||||
    xmpp = AdminCommands(args.jid, args.password, args.command)
 | 
			
		||||
    xmpp.register_plugin('xep_0133') # Service Administration
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,48 +1,37 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
from sleekxmpp import ClientXMPP, Iq
 | 
			
		||||
from sleekxmpp.exceptions import IqError, IqTimeout, XMPPError
 | 
			
		||||
from sleekxmpp.xmlstream import register_stanza_plugin
 | 
			
		||||
from sleekxmpp.xmlstream.handler import Callback
 | 
			
		||||
from sleekxmpp.xmlstream.matcher import StanzaPath
 | 
			
		||||
from slixmpp import ClientXMPP, Iq
 | 
			
		||||
from slixmpp.exceptions import IqError, IqTimeout, XMPPError
 | 
			
		||||
from slixmpp.xmlstream import register_stanza_plugin
 | 
			
		||||
from slixmpp.xmlstream.handler import Callback
 | 
			
		||||
from slixmpp.xmlstream.matcher import StanzaPath
 | 
			
		||||
from stanza import Action
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ActionBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class ActionBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that receives a custom stanza
 | 
			
		||||
    A simple Slixmpp bot that receives a custom stanza
 | 
			
		||||
    from another client.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
@@ -51,14 +40,13 @@ class ActionBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
        # our roster.
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
 | 
			
		||||
        self.registerHandler(
 | 
			
		||||
        self.register_handler(
 | 
			
		||||
          Callback('Some custom iq',
 | 
			
		||||
            StanzaPath('iq@type=set/action'),
 | 
			
		||||
            self._handle_action))
 | 
			
		||||
 | 
			
		||||
        self.add_event_handler('custom_action',
 | 
			
		||||
                self._handle_action_event,
 | 
			
		||||
                threaded=True)
 | 
			
		||||
                self._handle_action_event)
 | 
			
		||||
 | 
			
		||||
        register_stanza_plugin(Iq, Action)
 | 
			
		||||
 | 
			
		||||
@@ -88,10 +76,6 @@ class ActionBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
    def _handle_action_event(self, iq):
 | 
			
		||||
        """
 | 
			
		||||
        Respond to the custom action event.
 | 
			
		||||
 | 
			
		||||
        Since one of the actions is to disconnect, this
 | 
			
		||||
        event handler needs to be run in threaded mode, by
 | 
			
		||||
        using `threaded=True` in the `add_event_handler` call.
 | 
			
		||||
        """
 | 
			
		||||
        method = iq['action']['method']
 | 
			
		||||
        param = iq['action']['param']
 | 
			
		||||
@@ -112,62 +96,42 @@ class ActionBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the CommandBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = ActionBot(opts.jid, opts.password)
 | 
			
		||||
    xmpp = ActionBot(args.jid, args.password)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0050') # Adhoc Commands
 | 
			
		||||
    xmpp.register_plugin('xep_0199', {'keepalive': True, 'frequency':15})
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,46 +1,35 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp import Iq
 | 
			
		||||
from sleekxmpp.exceptions import XMPPError
 | 
			
		||||
from sleekxmpp.xmlstream import register_stanza_plugin
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp import Iq
 | 
			
		||||
from slixmpp.exceptions import XMPPError
 | 
			
		||||
from slixmpp.xmlstream import register_stanza_plugin
 | 
			
		||||
 | 
			
		||||
from stanza import Action
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ActionUserBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class ActionUserBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that sends a custom action stanza
 | 
			
		||||
    A simple Slixmpp bot that sends a custom action stanza
 | 
			
		||||
    to another client.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, other):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.action_provider = other
 | 
			
		||||
 | 
			
		||||
@@ -49,7 +38,7 @@ class ActionUserBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
        # and the XML streams are ready for use. We want to
 | 
			
		||||
        # listen for this event so that we we can initialize
 | 
			
		||||
        # our roster.
 | 
			
		||||
        self.add_event_handler("session_start", self.start, threaded=True)
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
        self.add_event_handler("message", self.message)
 | 
			
		||||
 | 
			
		||||
        register_stanza_plugin(Iq, Action)
 | 
			
		||||
@@ -93,10 +82,8 @@ class ActionUserBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
                iq2['type'] = 'set'
 | 
			
		||||
                iq2['action']['method'] = 'bye'
 | 
			
		||||
                iq2.send(block=False)
 | 
			
		||||
            
 | 
			
		||||
                # The wait=True delays the disconnect until the queue
 | 
			
		||||
                # of stanzas to be sent becomes empty.
 | 
			
		||||
                self.disconnect(wait=True)
 | 
			
		||||
 | 
			
		||||
                self.disconnect()
 | 
			
		||||
        except XMPPError:
 | 
			
		||||
            print('There was an error sending the custom action.')
 | 
			
		||||
 | 
			
		||||
@@ -111,65 +98,45 @@ class ActionUserBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("-o", "--other", dest="other",
 | 
			
		||||
                    help="JID providing custom stanza")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-o", "--other", dest="other",
 | 
			
		||||
                        help="JID providing custom stanza")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.other is None:
 | 
			
		||||
        opts.other = raw_input("JID Providing custom stanza: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.other is None:
 | 
			
		||||
        args.other = input("JID Providing custom stanza: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the CommandBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = ActionUserBot(opts.jid, opts.password, opts.other)
 | 
			
		||||
    xmpp = ActionUserBot(args.jid, args.password, args.other)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0050') # Adhoc Commands
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,30 @@
 | 
			
		||||
from sleekxmpp.xmlstream import ElementBase
 | 
			
		||||
from slixmpp.xmlstream import ElementBase
 | 
			
		||||
 | 
			
		||||
class Action(ElementBase):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A stanza class for XML content of the form:
 | 
			
		||||
 | 
			
		||||
    <action xmlns="sleekxmpp:custom:actions">
 | 
			
		||||
    <action xmlns="slixmpp:custom:actions">
 | 
			
		||||
      <method>X</method>
 | 
			
		||||
      <param>X</param>
 | 
			
		||||
      <status>X</status>
 | 
			
		||||
    </action>
 | 
			
		||||
    """
 | 
			
		||||
   
 | 
			
		||||
 | 
			
		||||
    #: The `name` field refers to the basic XML tag name of the
 | 
			
		||||
    #: stanza. Here, the tag name will be 'action'.
 | 
			
		||||
    name = 'action'
 | 
			
		||||
 | 
			
		||||
    #: The namespace of the main XML tag.
 | 
			
		||||
    namespace = 'sleekxmpp:custom:actions'
 | 
			
		||||
    namespace = 'slixmpp:custom:actions'
 | 
			
		||||
 | 
			
		||||
    #: The `plugin_attrib` value is the name that can be used
 | 
			
		||||
    #: with a parent stanza to access this stanza. For example
 | 
			
		||||
    #: from an Iq stanza object, accessing:
 | 
			
		||||
    #: 
 | 
			
		||||
    #:
 | 
			
		||||
    #:     iq['action']
 | 
			
		||||
    #: 
 | 
			
		||||
    #:
 | 
			
		||||
    #: would reference an Action object, and will even create
 | 
			
		||||
    #: an Action object and append it to the Iq stanza if
 | 
			
		||||
    #: one doesn't already exist.
 | 
			
		||||
@@ -49,8 +49,8 @@ class Action(ElementBase):
 | 
			
		||||
    #: the sub_interfaces set. For example, here all interfaces
 | 
			
		||||
    #: are marked as sub_interfaces, and so the XML produced will
 | 
			
		||||
    #: look like:
 | 
			
		||||
    #: 
 | 
			
		||||
    #:     <action xmlns="sleekxmpp:custom:actions">
 | 
			
		||||
    #:
 | 
			
		||||
    #:     <action xmlns="slixmpp:custom:actions">
 | 
			
		||||
    #:       <method>foo</method>
 | 
			
		||||
    #:     </action>
 | 
			
		||||
    sub_interfaces = interfaces
 | 
			
		||||
 
 | 
			
		||||
@@ -1,35 +1,24 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
from slixmpp.xmlstream.asyncio import asyncio
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Disco(sleekxmpp.ClientXMPP):
 | 
			
		||||
class Disco(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A demonstration for using basic service discovery.
 | 
			
		||||
@@ -42,7 +31,7 @@ class Disco(sleekxmpp.ClientXMPP):
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, target_jid, target_node='', get=''):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # Using service discovery requires the XEP-0030 plugin.
 | 
			
		||||
        self.register_plugin('xep_0030')
 | 
			
		||||
@@ -63,8 +52,9 @@ class Disco(sleekxmpp.ClientXMPP):
 | 
			
		||||
        # and the XML streams are ready for use. We want to
 | 
			
		||||
        # listen for this event so that we we can initialize
 | 
			
		||||
        # our roster.
 | 
			
		||||
        self.add_event_handler("session_start", self.start, threaded=True)
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
        Process the session_start event.
 | 
			
		||||
@@ -91,17 +81,15 @@ class Disco(sleekxmpp.ClientXMPP):
 | 
			
		||||
                # received. Non-blocking options would be to listen
 | 
			
		||||
                # for the disco_info event, or passing a handler
 | 
			
		||||
                # function using the callback parameter.
 | 
			
		||||
                info = self['xep_0030'].get_info(jid=self.target_jid,
 | 
			
		||||
                                                 node=self.target_node,
 | 
			
		||||
                                                 block=True)
 | 
			
		||||
            elif self.get in self.items_types:
 | 
			
		||||
                info = yield from self['xep_0030'].get_info(jid=self.target_jid,
 | 
			
		||||
                                                            node=self.target_node)
 | 
			
		||||
            if self.get in self.items_types:
 | 
			
		||||
                # The same applies from above. Listen for the
 | 
			
		||||
                # disco_items event or pass a callback function
 | 
			
		||||
                # if you need to process a non-blocking request.
 | 
			
		||||
                items = self['xep_0030'].get_items(jid=self.target_jid,
 | 
			
		||||
                                                   node=self.target_node,
 | 
			
		||||
                                                   block=True)
 | 
			
		||||
            else:
 | 
			
		||||
                items = yield from self['xep_0030'].get_items(jid=self.target_jid,
 | 
			
		||||
                                                              node=self.target_node)
 | 
			
		||||
            if self.get not in self.info_types and self.get not in self.items_types:
 | 
			
		||||
                logging.error("Invalid disco request type.")
 | 
			
		||||
                return
 | 
			
		||||
        except IqError as e:
 | 
			
		||||
@@ -136,69 +124,42 @@ class Disco(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    optp.version = '%%prog 0.1'
 | 
			
		||||
    optp.usage = "Usage: %%prog [options] %s <jid> [<node>]" % \
 | 
			
		||||
                             'all|info|items|identities|features'
 | 
			
		||||
    parser = ArgumentParser(description=Disco.__doc__)
 | 
			
		||||
 | 
			
		||||
    optp.add_option('-q','--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-d','--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-v','--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=5,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    parser.add_argument("-q","--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
    parser.add_argument("-d","--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    opts,args = optp.parse_args()
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("query", choices=["all", "info", "items", "identities", "features"])
 | 
			
		||||
    parser.add_argument("target_jid")
 | 
			
		||||
    parser.add_argument("node", nargs='?')
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if len(args) < 2:
 | 
			
		||||
        optp.print_help()
 | 
			
		||||
        exit()
 | 
			
		||||
 | 
			
		||||
    if len(args) == 2:
 | 
			
		||||
        args = (args[0], args[1], '')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the Disco browser.
 | 
			
		||||
    xmpp = Disco(opts.jid, opts.password, args[1], args[2], args[0])
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
    xmpp = Disco(args.jid, args.password, args.target_jid, args.node, args.query)
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										133
									
								
								examples/download_avatars.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										133
									
								
								examples/download_avatars.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,33 +1,21 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2012  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
import threading
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.exceptions import XMPPError
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.exceptions import XMPPError
 | 
			
		||||
from slixmpp import asyncio
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
FILE_TYPES = {
 | 
			
		||||
@@ -37,23 +25,29 @@ FILE_TYPES = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AvatarDownloader(sleekxmpp.ClientXMPP):
 | 
			
		||||
class AvatarDownloader(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A basic script for downloading the avatars for a user's contacts.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        self.add_event_handler("session_start", self.start, threaded=True)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
        self.add_event_handler("changed_status", self.wait_for_presences)
 | 
			
		||||
 | 
			
		||||
        self.add_event_handler('vcard_avatar_update', self.on_vcard_avatar)
 | 
			
		||||
        self.add_event_handler('avatar_metadata_publish', self.on_avatar)
 | 
			
		||||
 | 
			
		||||
        self.received = set()
 | 
			
		||||
        self.presences_received = threading.Event()
 | 
			
		||||
        self.presences_received = asyncio.Event()
 | 
			
		||||
        self.roster_received = asyncio.Event()
 | 
			
		||||
 | 
			
		||||
    def roster_received_cb(self, event):
 | 
			
		||||
        self.roster_received.set()
 | 
			
		||||
        self.presences_received.clear()
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
        Process the session_start event.
 | 
			
		||||
@@ -68,16 +62,20 @@ class AvatarDownloader(sleekxmpp.ClientXMPP):
 | 
			
		||||
                     data.
 | 
			
		||||
        """
 | 
			
		||||
        self.send_presence()
 | 
			
		||||
        self.get_roster()
 | 
			
		||||
        self.get_roster(callback=self.roster_received_cb)
 | 
			
		||||
 | 
			
		||||
        print('Waiting for presence updates...\n')
 | 
			
		||||
        self.presences_received.wait(15)
 | 
			
		||||
        self.disconnect(wait=True)
 | 
			
		||||
        yield from self.roster_received.wait()
 | 
			
		||||
        print('Roster received')
 | 
			
		||||
        yield from self.presences_received.wait()
 | 
			
		||||
        self.disconnect()
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def on_vcard_avatar(self, pres):
 | 
			
		||||
        print("Received vCard avatar update from %s" % pres['from'].bare)
 | 
			
		||||
        try:
 | 
			
		||||
            result = self['xep_0054'].get_vcard(pres['from'], cached=True)
 | 
			
		||||
            result = yield from self['xep_0054'].get_vcard(pres['from'].bare, cached=True,
 | 
			
		||||
                                                           timeout=5)
 | 
			
		||||
        except XMPPError:
 | 
			
		||||
            print("Error retrieving avatar for %s" % pres['from'])
 | 
			
		||||
            return
 | 
			
		||||
@@ -88,16 +86,18 @@ class AvatarDownloader(sleekxmpp.ClientXMPP):
 | 
			
		||||
                pres['from'].bare,
 | 
			
		||||
                pres['vcard_temp_update']['photo'],
 | 
			
		||||
                filetype)
 | 
			
		||||
        with open(filename, 'w+') as img:
 | 
			
		||||
        with open(filename, 'wb+') as img:
 | 
			
		||||
            img.write(avatar['BINVAL'])
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def on_avatar(self, msg):
 | 
			
		||||
        print("Received avatar update from %s" % msg['from'])
 | 
			
		||||
        metadata = msg['pubsub_event']['items']['item']['avatar_metadata']
 | 
			
		||||
        for info in metadata['items']:
 | 
			
		||||
            if not info['url']:
 | 
			
		||||
                try:
 | 
			
		||||
                    result = self['xep_0084'].retrieve_avatar(msg['from'], info['id'])
 | 
			
		||||
                    result = yield from self['xep_0084'].retrieve_avatar(msg['from'].bare, info['id'],
 | 
			
		||||
                                                                         timeout=5)
 | 
			
		||||
                except XMPPError:
 | 
			
		||||
                    print("Error retrieving avatar for %s" % msg['from'])
 | 
			
		||||
                    return
 | 
			
		||||
@@ -106,7 +106,7 @@ class AvatarDownloader(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
                filetype = FILE_TYPES.get(metadata['type'], 'png')
 | 
			
		||||
                filename = 'avatar_%s_%s.%s' % (msg['from'].bare, info['id'], filetype)
 | 
			
		||||
                with open(filename, 'w+') as img:
 | 
			
		||||
                with open(filename, 'wb+') as img:
 | 
			
		||||
                    img.write(avatar['value'])
 | 
			
		||||
            else:
 | 
			
		||||
                # We could retrieve the avatar via HTTP, etc here instead.
 | 
			
		||||
@@ -117,6 +117,7 @@ class AvatarDownloader(sleekxmpp.ClientXMPP):
 | 
			
		||||
        Wait to receive updates from all roster contacts.
 | 
			
		||||
        """
 | 
			
		||||
        self.received.add(pres['from'].bare)
 | 
			
		||||
        print((len(self.received), len(self.client_roster.keys())))
 | 
			
		||||
        if len(self.received) >= len(self.client_roster.keys()):
 | 
			
		||||
            self.presences_received.set()
 | 
			
		||||
        else:
 | 
			
		||||
@@ -125,60 +126,40 @@ class AvatarDownloader(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    optp.add_option('-q','--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-d','--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-v','--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=5,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
    parser.add_argument("-q","--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
    parser.add_argument("-d","--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    opts,args = optp.parse_args()
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    xmpp = AvatarDownloader(opts.jid, opts.password)
 | 
			
		||||
    xmpp = AvatarDownloader(args.jid, args.password)
 | 
			
		||||
    xmpp.register_plugin('xep_0054')
 | 
			
		||||
    xmpp.register_plugin('xep_0153')
 | 
			
		||||
    xmpp.register_plugin('xep_0084')
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,41 +1,30 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EchoBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class EchoBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that will echo messages it
 | 
			
		||||
    A simple Slixmpp bot that will echo messages it
 | 
			
		||||
    receives, along with a short thank you message.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
@@ -83,75 +72,42 @@ class EchoBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser(description=EchoBot.__doc__)
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the EchoBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = EchoBot(opts.jid, opts.password)
 | 
			
		||||
    xmpp = EchoBot(args.jid, args.password)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0060') # PubSub
 | 
			
		||||
    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
			
		||||
 | 
			
		||||
    # If you are connecting to Facebook and wish to use the
 | 
			
		||||
    # X-FACEBOOK-PLATFORM authentication mechanism, you will need
 | 
			
		||||
    # your API key and an access token. Then you'll set:
 | 
			
		||||
    # xmpp.credentials['api_key'] = 'THE_API_KEY'
 | 
			
		||||
    # xmpp.credentials['access_token'] = 'THE_ACCESS_TOKEN'
 | 
			
		||||
 | 
			
		||||
    # If you are connecting to MSN, then you will need an
 | 
			
		||||
    # access token, and it does not matter what JID you
 | 
			
		||||
    # specify other than that the domain is 'messenger.live.com',
 | 
			
		||||
    # so '_@messenger.live.com' will work. You can specify
 | 
			
		||||
    # the access token as so:
 | 
			
		||||
    # xmpp.credentials['access_token'] = 'THE_ACCESS_TOKEN'
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,37 +1,26 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.componentxmpp import ComponentXMPP
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.componentxmpp import ComponentXMPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EchoComponent(ComponentXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP component that echoes messages.
 | 
			
		||||
    A simple Slixmpp component that echoes messages.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, secret, server, port):
 | 
			
		||||
@@ -67,56 +56,50 @@ class EchoComponent(ComponentXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser(description=EchoComponent.__doc__)
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("-s", "--server", dest="server",
 | 
			
		||||
                    help="server to connect to")
 | 
			
		||||
    optp.add_option("-P", "--port", dest="port",
 | 
			
		||||
                    help="port to connect to")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-s", "--server", dest="server",
 | 
			
		||||
                        help="server to connect to")
 | 
			
		||||
    parser.add_argument("-P", "--port", dest="port",
 | 
			
		||||
                        help="port to connect to")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Component JID: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.server is None:
 | 
			
		||||
        opts.server = raw_input("Server: ")
 | 
			
		||||
    if opts.port is None:
 | 
			
		||||
        opts.port = int(raw_input("Port: "))
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Component JID: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.server is None:
 | 
			
		||||
        args.server = input("Server: ")
 | 
			
		||||
    if args.port is None:
 | 
			
		||||
        args.port = int(input("Port: "))
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    # Setup the EchoComponent and register plugins. Note that while plugins
 | 
			
		||||
    # may have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = EchoComponent(opts.jid, opts.password, opts.server, opts.port)
 | 
			
		||||
    xmpp.registerPlugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.registerPlugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.registerPlugin('xep_0060') # PubSub
 | 
			
		||||
    xmpp.registerPlugin('xep_0199') # XMPP Ping
 | 
			
		||||
    xmpp = EchoComponent(args.jid, args.password, args.server, args.port)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0060') # PubSub
 | 
			
		||||
    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,46 +1,34 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
import ssl
 | 
			
		||||
from sleekxmpp.xmlstream import cert
 | 
			
		||||
from slixmpp.xmlstream import cert
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GTalkBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class GTalkBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A demonstration of using SleekXMPP with accounts from a Google Apps
 | 
			
		||||
    A demonstration of using Slixmpp with accounts from a Google Apps
 | 
			
		||||
    account with a custom domain, because it requires custom certificate
 | 
			
		||||
    validation.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
@@ -104,62 +92,42 @@ class GTalkBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the GTalkBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = GTalkBot(opts.jid, opts.password)
 | 
			
		||||
    xmpp = GTalkBot(args.jid, args.password)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0060') # PubSub
 | 
			
		||||
    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,45 +1,31 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IBBReceiver(sleekxmpp.ClientXMPP):
 | 
			
		||||
class IBBReceiver(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A basic example of creating and using an in-band bytestream.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
    def __init__(self, jid, password, filename):
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
        self.register_plugin('xep_0047', {
 | 
			
		||||
            'accept_stream': self.accept_stream
 | 
			
		||||
        }) # In-band Bytestreams
 | 
			
		||||
        self.file = open(filename, 'wb')
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
@@ -50,6 +36,7 @@ class IBBReceiver(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
        self.add_event_handler("ibb_stream_start", self.stream_opened)
 | 
			
		||||
        self.add_event_handler("ibb_stream_data", self.stream_data)
 | 
			
		||||
        self.add_event_handler("ibb_stream_end", self.stream_closed)
 | 
			
		||||
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
@@ -67,83 +54,59 @@ class IBBReceiver(sleekxmpp.ClientXMPP):
 | 
			
		||||
        self.send_presence()
 | 
			
		||||
        self.get_roster()
 | 
			
		||||
 | 
			
		||||
    def accept_stream(self, iq):
 | 
			
		||||
        """
 | 
			
		||||
        Check that it is ok to accept a stream request. 
 | 
			
		||||
 | 
			
		||||
        Controlling stream acceptance can be done via either:
 | 
			
		||||
            - setting 'auto_accept' to False in the plugin
 | 
			
		||||
              configuration. The default is True.
 | 
			
		||||
            - setting 'accept_stream' to a function which accepts
 | 
			
		||||
              an Iq stanza as its argument, like this one.
 | 
			
		||||
 | 
			
		||||
        The accept_stream function will be used if it exists, and the
 | 
			
		||||
        auto_accept value will be used otherwise.
 | 
			
		||||
        """
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def stream_opened(self, stream):
 | 
			
		||||
        # NOTE: IBB streams are bi-directional, so the original sender is
 | 
			
		||||
        # now the opened stream's receiver.
 | 
			
		||||
        print('Stream opened: %s from %s' % (stream.sid, stream.receiver))
 | 
			
		||||
        print('Stream opened: %s from %s' % (stream.sid, stream.peer_jid))
 | 
			
		||||
 | 
			
		||||
        # You could run a loop reading from the stream using stream.recv(),
 | 
			
		||||
        # or use the ibb_stream_data event.
 | 
			
		||||
    def stream_data(self, stream):
 | 
			
		||||
        self.file.write(stream.read())
 | 
			
		||||
 | 
			
		||||
    def stream_data(self, event):
 | 
			
		||||
        print(event['data'])
 | 
			
		||||
    def stream_closed(self, stream):
 | 
			
		||||
        print('Stream closed: %s from %s' % (stream.sid, stream.peer_jid))
 | 
			
		||||
        self.file.close()
 | 
			
		||||
        self.disconnect()
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-o", "--out", dest="filename",
 | 
			
		||||
                        help="file to save to")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.filename is None:
 | 
			
		||||
        args.filename = input("File path: ")
 | 
			
		||||
 | 
			
		||||
    xmpp = IBBReceiver(opts.jid, opts.password)
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
    # Setup the IBBReceiver and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = IBBReceiver(args.jid, args.password, args.filename)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0047', {
 | 
			
		||||
        'auto_accept': True
 | 
			
		||||
    }) # In-band Bytestreams
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process(forever=False)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,43 +1,36 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import asyncio
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IBBSender(sleekxmpp.ClientXMPP):
 | 
			
		||||
class IBBSender(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A basic example of creating and using an in-band bytestream.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, receiver, filename):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
    def __init__(self, jid, password, receiver, filename, use_messages=False):
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.receiver = receiver
 | 
			
		||||
        self.filename = filename
 | 
			
		||||
 | 
			
		||||
        self.file = open(filename, 'rb')
 | 
			
		||||
        self.use_messages = use_messages
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
@@ -46,6 +39,7 @@ class IBBSender(sleekxmpp.ClientXMPP):
 | 
			
		||||
        # our roster.
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
        Process the session_start event.
 | 
			
		||||
@@ -62,84 +56,70 @@ class IBBSender(sleekxmpp.ClientXMPP):
 | 
			
		||||
        self.send_presence()
 | 
			
		||||
        self.get_roster()
 | 
			
		||||
 | 
			
		||||
        # For the purpose of demonstration, we'll set a very small block
 | 
			
		||||
        # size. The default block size is 4096. We'll also use a window
 | 
			
		||||
        # allowing sending multiple blocks at a time; in this case, three
 | 
			
		||||
        # block transfers may be in progress at any time.
 | 
			
		||||
        stream = self['xep_0047'].open_stream(self.receiver)
 | 
			
		||||
        try:
 | 
			
		||||
            # Open the IBB stream in which to write to.
 | 
			
		||||
            stream = yield from self['xep_0047'].open_stream(self.receiver, use_messages=self.use_messages)
 | 
			
		||||
 | 
			
		||||
        with open(self.filename) as f:
 | 
			
		||||
            data = f.read()
 | 
			
		||||
            stream.sendall(data)
 | 
			
		||||
            # If you want to send in-memory bytes, use stream.sendall() instead.
 | 
			
		||||
            yield from stream.sendfile(self.file, timeout=10)
 | 
			
		||||
 | 
			
		||||
            # And finally close the stream.
 | 
			
		||||
            yield from stream.close(timeout=10)
 | 
			
		||||
        except (IqError, IqTimeout):
 | 
			
		||||
            print('File transfer errored')
 | 
			
		||||
        else:
 | 
			
		||||
            print('File transfer finished')
 | 
			
		||||
        finally:
 | 
			
		||||
            self.file.close()
 | 
			
		||||
            self.disconnect()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("-r", "--receiver", dest="receiver",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-f", "--file", dest="filename",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-r", "--receiver", dest="receiver",
 | 
			
		||||
                        help="JID of the receiver")
 | 
			
		||||
    parser.add_argument("-f", "--file", dest="filename",
 | 
			
		||||
                        help="file to send")
 | 
			
		||||
    parser.add_argument("-m", "--use-messages", action="store_true",
 | 
			
		||||
                        help="use messages instead of iqs for file transfer")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.receiver is None:
 | 
			
		||||
        opts.receiver = raw_input("Receiver: ")
 | 
			
		||||
    if opts.filename is None:
 | 
			
		||||
        opts.filename = raw_input("File path: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.receiver is None:
 | 
			
		||||
        args.receiver = input("Receiver: ")
 | 
			
		||||
    if args.filename is None:
 | 
			
		||||
        args.filename = input("File path: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the EchoBot and register plugins. Note that while plugins may
 | 
			
		||||
    # Setup the IBBSender and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = IBBSender(opts.jid, opts.password, opts.receiver, opts.filename)
 | 
			
		||||
    xmpp = IBBSender(args.jid, args.password, args.receiver, args.filename, args.use_messages)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0047') # In-band Bytestreams
 | 
			
		||||
    xmpp.register_plugin('xep_0060') # PubSub
 | 
			
		||||
    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process(forever=False)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										107
									
								
								examples/migrate_roster.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										107
									
								
								examples/migrate_roster.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Setup the command line arguments.
 | 
			
		||||
parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
# Output verbosity options.
 | 
			
		||||
parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                    action="store_const", dest="loglevel",
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                    action="store_const", dest="loglevel",
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
# JID and password options.
 | 
			
		||||
parser.add_argument("--oldjid", dest="old_jid",
 | 
			
		||||
                    help="JID of the old account")
 | 
			
		||||
parser.add_argument("--oldpassword", dest="old_password",
 | 
			
		||||
                    help="password of the old account")
 | 
			
		||||
 | 
			
		||||
parser.add_argument("--newjid", dest="new_jid",
 | 
			
		||||
                    help="JID of the old account")
 | 
			
		||||
parser.add_argument("--newpassword", dest="new_password",
 | 
			
		||||
                    help="password of the old account")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
# Setup logging.
 | 
			
		||||
logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                    format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
if args.old_jid is None:
 | 
			
		||||
    args.old_jid = input("Old JID: ")
 | 
			
		||||
if args.old_password is None:
 | 
			
		||||
    args.old_password = getpass("Old Password: ")
 | 
			
		||||
 | 
			
		||||
if args.new_jid is None:
 | 
			
		||||
    args.new_jid = input("New JID: ")
 | 
			
		||||
if args.new_password is None:
 | 
			
		||||
    args.new_password = getpass("New Password: ")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
old_xmpp = slixmpp.ClientXMPP(args.old_jid, args.old_password)
 | 
			
		||||
 | 
			
		||||
# If you are connecting to Facebook and wish to use the
 | 
			
		||||
# X-FACEBOOK-PLATFORM authentication mechanism, you will need
 | 
			
		||||
# your API key and an access token. Then you'll set:
 | 
			
		||||
# xmpp.credentials['api_key'] = 'THE_API_KEY'
 | 
			
		||||
# xmpp.credentials['access_token'] = 'THE_ACCESS_TOKEN'
 | 
			
		||||
 | 
			
		||||
# If you are connecting to MSN, then you will need an
 | 
			
		||||
# access token, and it does not matter what JID you
 | 
			
		||||
# specify other than that the domain is 'messenger.live.com',
 | 
			
		||||
# so '_@messenger.live.com' will work. You can specify
 | 
			
		||||
# the access token as so:
 | 
			
		||||
# xmpp.credentials['access_token'] = 'THE_ACCESS_TOKEN'
 | 
			
		||||
 | 
			
		||||
# If you are working with an OpenFire server, you may need
 | 
			
		||||
# to adjust the SSL version used:
 | 
			
		||||
# xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
# If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
# xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
roster = []
 | 
			
		||||
 | 
			
		||||
def on_session(event):
 | 
			
		||||
    roster.append(old_xmpp.get_roster())
 | 
			
		||||
    old_xmpp.disconnect()
 | 
			
		||||
old_xmpp.add_event_handler('session_start', on_session)
 | 
			
		||||
 | 
			
		||||
if old_xmpp.connect():
 | 
			
		||||
    old_xmpp.process(block=True)
 | 
			
		||||
 | 
			
		||||
if not roster:
 | 
			
		||||
    print('No roster to migrate')
 | 
			
		||||
    sys.exit()
 | 
			
		||||
 | 
			
		||||
new_xmpp = slixmpp.ClientXMPP(args.new_jid, args.new_password)
 | 
			
		||||
def on_session2(event):
 | 
			
		||||
    new_xmpp.get_roster()
 | 
			
		||||
    new_xmpp.send_presence()
 | 
			
		||||
 | 
			
		||||
    logging.info(roster[0])
 | 
			
		||||
    data = roster[0]['roster']['items']
 | 
			
		||||
    logging.info(data)
 | 
			
		||||
 | 
			
		||||
    for jid, item in data.items():
 | 
			
		||||
        if item['subscription'] != 'none':
 | 
			
		||||
            new_xmpp.send_presence(ptype='subscribe', pto=jid)
 | 
			
		||||
        new_xmpp.update_roster(jid,
 | 
			
		||||
                name = item['name'],
 | 
			
		||||
                groups = item['groups'])
 | 
			
		||||
        new_xmpp.disconnect()
 | 
			
		||||
new_xmpp.add_event_handler('session_start', on_session2)
 | 
			
		||||
 | 
			
		||||
new_xmpp.connect()
 | 
			
		||||
new_xmpp.process()
 | 
			
		||||
@@ -1,42 +1,31 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MUCBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class MUCBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that will greets those
 | 
			
		||||
    A simple Slixmpp bot that will greets those
 | 
			
		||||
    who enter the room, and acknowledge any messages
 | 
			
		||||
    that mentions the bot's nickname.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, room, nick):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.room = room
 | 
			
		||||
        self.nick = nick
 | 
			
		||||
@@ -132,62 +121,49 @@ class MUCBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("-r", "--room", dest="room",
 | 
			
		||||
                    help="MUC room to join")
 | 
			
		||||
    optp.add_option("-n", "--nick", dest="nick",
 | 
			
		||||
                    help="MUC nickname")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-r", "--room", dest="room",
 | 
			
		||||
                        help="MUC room to join")
 | 
			
		||||
    parser.add_argument("-n", "--nick", dest="nick",
 | 
			
		||||
                        help="MUC nickname")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.room is None:
 | 
			
		||||
        opts.room = raw_input("MUC room: ")
 | 
			
		||||
    if opts.nick is None:
 | 
			
		||||
        opts.nick = raw_input("MUC nickname: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.room is None:
 | 
			
		||||
        args.room = input("MUC room: ")
 | 
			
		||||
    if args.nick is None:
 | 
			
		||||
        args.nick = input("MUC nickname: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the MUCBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = MUCBot(opts.jid, opts.password, opts.room, opts.nick)
 | 
			
		||||
    xmpp = MUCBot(args.jid, args.password, args.room, args.nick)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0045') # Multi-User Chat
 | 
			
		||||
    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										123
									
								
								examples/ping.py
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								examples/ping.py
									
									
									
									
									
								
							@@ -1,43 +1,34 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
from slixmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
from slixmpp import asyncio
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PingTest(sleekxmpp.ClientXMPP):
 | 
			
		||||
class PingTest(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that will send a ping request
 | 
			
		||||
    A simple Slixmpp bot that will send a ping request
 | 
			
		||||
    to a given JID.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, pingjid):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        if pingjid is None:
 | 
			
		||||
            pingjid = self.jid
 | 
			
		||||
            pingjid = self.boundjid.bare
 | 
			
		||||
        self.pingjid = pingjid
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
@@ -45,8 +36,9 @@ class PingTest(sleekxmpp.ClientXMPP):
 | 
			
		||||
        # and the XML streams are ready for use. We want to
 | 
			
		||||
        # listen for this event so that we we can initialize
 | 
			
		||||
        # our roster.
 | 
			
		||||
        self.add_event_handler("session_start", self.start, threaded=True)
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
        Process the session_start event.
 | 
			
		||||
@@ -62,80 +54,61 @@ class PingTest(sleekxmpp.ClientXMPP):
 | 
			
		||||
        """
 | 
			
		||||
        self.send_presence()
 | 
			
		||||
        self.get_roster()
 | 
			
		||||
        result = self['xep_0199'].send_ping(self.pingjid,
 | 
			
		||||
                                            timeout=10,
 | 
			
		||||
                                            errorfalse=True)
 | 
			
		||||
        logging.info("Pinging...")
 | 
			
		||||
        if result is False:
 | 
			
		||||
            logging.info("Couldn't ping.")
 | 
			
		||||
            self.disconnect()
 | 
			
		||||
            sys.exit(1)
 | 
			
		||||
        else:
 | 
			
		||||
            logging.info("Success! RTT: %s", str(result))
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            rtt = yield from self['xep_0199'].ping(self.pingjid,
 | 
			
		||||
                                                   timeout=10)
 | 
			
		||||
            logging.info("Success! RTT: %s", rtt)
 | 
			
		||||
        except IqError as e:
 | 
			
		||||
            logging.info("Error pinging %s: %s",
 | 
			
		||||
                    self.pingjid,
 | 
			
		||||
                    e.iq['error']['condition'])
 | 
			
		||||
        except IqTimeout:
 | 
			
		||||
            logging.info("No response from %s", self.pingjid)
 | 
			
		||||
        finally:
 | 
			
		||||
            self.disconnect()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-t', '--pingto', help='set jid to ping',
 | 
			
		||||
                    action='store', type='string', dest='pingjid',
 | 
			
		||||
                    default=None)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-t", "--pingto", help="set jid to ping",
 | 
			
		||||
                        dest="pingjid", default=None)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the PingTest and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = PingTest(opts.jid, opts.password, opts.pingjid)
 | 
			
		||||
    xmpp = PingTest(args.jid, args.password, args.pingjid)
 | 
			
		||||
    xmpp.register_plugin('xep_0030')  # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004')  # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0060')  # PubSub
 | 
			
		||||
    xmpp.register_plugin('xep_0199')  # XMPP Ping
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,41 +1,30 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EchoBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class EchoBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that will echo messages it
 | 
			
		||||
    A simple Slixmpp bot that will echo messages it
 | 
			
		||||
    receives, along with a short thank you message.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
@@ -82,87 +71,65 @@ class EchoBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("--phost", dest="proxy_host",
 | 
			
		||||
                    help="Proxy hostname")
 | 
			
		||||
    optp.add_option("--pport", dest="proxy_port",
 | 
			
		||||
                    help="Proxy port")
 | 
			
		||||
    optp.add_option("--puser", dest="proxy_user",
 | 
			
		||||
                    help="Proxy username")
 | 
			
		||||
    optp.add_option("--ppass", dest="proxy_pass",
 | 
			
		||||
                    help="Proxy password")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("--phost", dest="proxy_host",
 | 
			
		||||
                        help="Proxy hostname")
 | 
			
		||||
    parser.add_argument("--pport", dest="proxy_port",
 | 
			
		||||
                        help="Proxy port")
 | 
			
		||||
    parser.add_argument("--puser", dest="proxy_user",
 | 
			
		||||
                        help="Proxy username")
 | 
			
		||||
    parser.add_argument("--ppass", dest="proxy_pass",
 | 
			
		||||
                        help="Proxy password")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.proxy_host is None:
 | 
			
		||||
        opts.proxy_host = raw_input("Proxy host: ")
 | 
			
		||||
    if opts.proxy_port is None:
 | 
			
		||||
        opts.proxy_port = raw_input("Proxy port: ")
 | 
			
		||||
    if opts.proxy_user is None:
 | 
			
		||||
        opts.proxy_user = raw_input("Proxy username: ")
 | 
			
		||||
    if opts.proxy_pass is None and opts.proxy_user:
 | 
			
		||||
        opts.proxy_pass = getpass.getpass("Proxy password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.proxy_host is None:
 | 
			
		||||
        args.proxy_host = input("Proxy host: ")
 | 
			
		||||
    if args.proxy_port is None:
 | 
			
		||||
        args.proxy_port = input("Proxy port: ")
 | 
			
		||||
    if args.proxy_user is None:
 | 
			
		||||
        args.proxy_user = input("Proxy username: ")
 | 
			
		||||
    if args.proxy_pass is None and args.proxy_user:
 | 
			
		||||
        args.proxy_pass = getpass("Proxy password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the EchoBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = EchoBot(opts.jid, opts.password)
 | 
			
		||||
    xmpp = EchoBot(args.jid, args.password)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0060') # PubSub
 | 
			
		||||
    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    xmpp.use_proxy = True
 | 
			
		||||
    xmpp.proxy_config = {
 | 
			
		||||
        'host': opts.proxy_host,
 | 
			
		||||
        'port': int(opts.proxy_port),
 | 
			
		||||
        'username': opts.proxy_user,
 | 
			
		||||
        'password': opts.proxy_pass}
 | 
			
		||||
        'host': args.proxy_host,
 | 
			
		||||
        'port': int(args.proxy_port),
 | 
			
		||||
        'username': args.proxy_user,
 | 
			
		||||
        'password': args.proxy_pass}
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										156
									
								
								examples/pubsub_client.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										156
									
								
								examples/pubsub_client.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,26 +1,23 @@
 | 
			
		||||
import sys
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.xmlstream import ET, tostring
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.xmlstream import ET, tostring
 | 
			
		||||
from slixmpp.xmlstream.asyncio import asyncio
 | 
			
		||||
 | 
			
		||||
def make_callback():
 | 
			
		||||
    future = asyncio.Future()
 | 
			
		||||
    def callback(result):
 | 
			
		||||
        future.set_result(result)
 | 
			
		||||
    return future, callback
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
class PubsubClient(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PubsubClient(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, server, 
 | 
			
		||||
    def __init__(self, jid, password, server,
 | 
			
		||||
                       node=None, action='list', data=''):
 | 
			
		||||
        super(PubsubClient, self).__init__(jid, password)
 | 
			
		||||
 | 
			
		||||
@@ -28,7 +25,7 @@ class PubsubClient(sleekxmpp.ClientXMPP):
 | 
			
		||||
        self.register_plugin('xep_0059')
 | 
			
		||||
        self.register_plugin('xep_0060')
 | 
			
		||||
 | 
			
		||||
        self.actions = ['nodes', 'create', 'delete', 
 | 
			
		||||
        self.actions = ['nodes', 'create', 'delete',
 | 
			
		||||
                        'publish', 'get', 'retract',
 | 
			
		||||
                        'purge', 'subscribe', 'unsubscribe']
 | 
			
		||||
 | 
			
		||||
@@ -37,7 +34,7 @@ class PubsubClient(sleekxmpp.ClientXMPP):
 | 
			
		||||
        self.data = data
 | 
			
		||||
        self.pubsub_server = server
 | 
			
		||||
 | 
			
		||||
        self.add_event_handler('session_start', self.start, threaded=True)
 | 
			
		||||
        self.add_event_handler('session_start', self.start)
 | 
			
		||||
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        self.get_roster()
 | 
			
		||||
@@ -50,8 +47,10 @@ class PubsubClient(sleekxmpp.ClientXMPP):
 | 
			
		||||
        self.disconnect()
 | 
			
		||||
 | 
			
		||||
    def nodes(self):
 | 
			
		||||
        future, callback = make_callback()
 | 
			
		||||
        try:
 | 
			
		||||
            result = self['xep_0060'].get_nodes(self.pubsub_server, self.node)
 | 
			
		||||
            self['xep_0060'].get_nodes(self.pubsub_server, self.node, callback=callback)
 | 
			
		||||
            result = yield from future
 | 
			
		||||
            for item in result['disco_items']['items']:
 | 
			
		||||
                print('  - %s' % str(item))
 | 
			
		||||
        except:
 | 
			
		||||
@@ -72,16 +71,20 @@ class PubsubClient(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    def publish(self):
 | 
			
		||||
        payload = ET.fromstring("<test xmlns='test'>%s</test>" % self.data)
 | 
			
		||||
        future, callback = make_callback()
 | 
			
		||||
        try:
 | 
			
		||||
            result = self['xep_0060'].publish(self.pubsub_server, self.node, payload=payload)
 | 
			
		||||
            self['xep_0060'].publish(self.pubsub_server, self.node, payload=payload, callback=callback)
 | 
			
		||||
            result = yield from future
 | 
			
		||||
            id = result['pubsub']['publish']['item']['id']
 | 
			
		||||
            print('Published at item id: %s' % id)
 | 
			
		||||
        except:
 | 
			
		||||
            logging.error('Could not publish to: %s' % self.node)
 | 
			
		||||
 | 
			
		||||
    def get(self):
 | 
			
		||||
        future, callback = make_callback()
 | 
			
		||||
        try:
 | 
			
		||||
            result = self['xep_0060'].get_item(self.pubsub_server, self.node, self.data)
 | 
			
		||||
            self['xep_0060'].get_item(self.pubsub_server, self.node, self.data, callback=callback)
 | 
			
		||||
            result = yield from future
 | 
			
		||||
            for item in result['pubsub']['items']['substanzas']:
 | 
			
		||||
                print('Retrieved item %s: %s' % (item['id'], tostring(item['payload'])))
 | 
			
		||||
        except:
 | 
			
		||||
@@ -89,28 +92,28 @@ class PubsubClient(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    def retract(self):
 | 
			
		||||
        try:
 | 
			
		||||
            result = self['xep_0060'].retract(self.pubsub_server, self.node, self.data)
 | 
			
		||||
            self['xep_0060'].retract(self.pubsub_server, self.node, self.data)
 | 
			
		||||
            print('Retracted item %s from node %s' % (self.data, self.node))
 | 
			
		||||
        except:
 | 
			
		||||
            logging.error('Could not retract item %s from node %s' % (self.data, self.node))
 | 
			
		||||
 | 
			
		||||
    def purge(self):
 | 
			
		||||
        try:
 | 
			
		||||
            result = self['xep_0060'].purge(self.pubsub_server, self.node)
 | 
			
		||||
            self['xep_0060'].purge(self.pubsub_server, self.node)
 | 
			
		||||
            print('Purged all items from node %s' % self.node)
 | 
			
		||||
        except:
 | 
			
		||||
            logging.error('Could not purge items from node %s' % self.node)
 | 
			
		||||
 | 
			
		||||
    def subscribe(self):
 | 
			
		||||
        try:
 | 
			
		||||
            result = self['xep_0060'].subscribe(self.pubsub_server, self.node)
 | 
			
		||||
            self['xep_0060'].subscribe(self.pubsub_server, self.node)
 | 
			
		||||
            print('Subscribed %s to node %s' % (self.boundjid.bare, self.node))
 | 
			
		||||
        except:
 | 
			
		||||
            logging.error('Could not subscribe %s to node %s' % (self.boundjid.bare, self.node))
 | 
			
		||||
 | 
			
		||||
    def unsubscribe(self):
 | 
			
		||||
        try:
 | 
			
		||||
            result = self['xep_0060'].unsubscribe(self.pubsub_server, self.node)
 | 
			
		||||
            self['xep_0060'].unsubscribe(self.pubsub_server, self.node)
 | 
			
		||||
            print('Unsubscribed %s from node %s' % (self.boundjid.bare, self.node))
 | 
			
		||||
        except:
 | 
			
		||||
            logging.error('Could not unsubscribe %s from node %s' % (self.boundjid.bare, self.node))
 | 
			
		||||
@@ -120,79 +123,52 @@ class PubsubClient(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    optp.version = '%%prog 0.1'
 | 
			
		||||
    optp.usage = "Usage: %%prog [options] <jid> " + \
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
    parser.version = '%%prog 0.1'
 | 
			
		||||
    parser.usage = "Usage: %%prog [options] <jid> " + \
 | 
			
		||||
                             'nodes|create|delete|purge|subscribe|unsubscribe|publish|retract|get' + \
 | 
			
		||||
                             ' [<node> <data>]'
 | 
			
		||||
 | 
			
		||||
    optp.add_option('-q','--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-d','--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-v','--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=5,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    parser.add_argument("-q","--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
    parser.add_argument("-d","--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    opts,args = optp.parse_args()
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    parser.add_argument("server")
 | 
			
		||||
    parser.add_argument("action", choice=["nodes", "create", "delete", "purge", "subscribe", "unsubscribe", "publish", "retract", "get"])
 | 
			
		||||
    parser.add_argument("node", nargs='?')
 | 
			
		||||
    parser.add_argument("data", nargs='?')
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if len(args) < 2:
 | 
			
		||||
        optp.print_help()
 | 
			
		||||
        exit()
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    if len(args) == 2:
 | 
			
		||||
        args = (args[0], args[1], '', '', '')
 | 
			
		||||
    elif len(args) == 3:
 | 
			
		||||
        args = (args[0], args[1], args[2], '', '')
 | 
			
		||||
    elif len(args) == 4:
 | 
			
		||||
        args = (args[0], args[1], args[2], args[3], '')
 | 
			
		||||
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the Pubsub client
 | 
			
		||||
    xmpp = PubsubClient(opts.jid, opts.password,
 | 
			
		||||
                        server=args[0],
 | 
			
		||||
                        node=args[2],
 | 
			
		||||
                        action=args[1],
 | 
			
		||||
                        data=args[3])
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
    xmpp = PubsubClient(args.jid, args.password,
 | 
			
		||||
                        server=args.server,
 | 
			
		||||
                        node=args.node,
 | 
			
		||||
                        action=args.action,
 | 
			
		||||
                        data=args.data)
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										91
									
								
								examples/pubsub_events.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										91
									
								
								examples/pubsub_events.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,26 +1,17 @@
 | 
			
		||||
import sys
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.xmlstream import ET, tostring
 | 
			
		||||
from sleekxmpp.xmlstream.matcher import StanzaPath
 | 
			
		||||
from sleekxmpp.xmlstream.handler import Callback
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.xmlstream import ET, tostring
 | 
			
		||||
from slixmpp.xmlstream.matcher import StanzaPath
 | 
			
		||||
from slixmpp.xmlstream.handler import Callback
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PubsubEvents(sleekxmpp.ClientXMPP):
 | 
			
		||||
class PubsubEvents(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        super(PubsubEvents, self).__init__(jid, password)
 | 
			
		||||
@@ -77,7 +68,7 @@ class PubsubEvents(sleekxmpp.ClientXMPP):
 | 
			
		||||
        """Handle receiving a node deletion event."""
 | 
			
		||||
        print('Deleted node %s' % (
 | 
			
		||||
           msg['pubsub_event']['delete']['node']))
 | 
			
		||||
 
 | 
			
		||||
 | 
			
		||||
    def _config(self, msg):
 | 
			
		||||
        """Handle receiving a node configuration event."""
 | 
			
		||||
        print('Configured node %s:' % (
 | 
			
		||||
@@ -93,59 +84,39 @@ class PubsubEvents(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    logging.info("Run this in conjunction with the pubsub_client.py " + \
 | 
			
		||||
                 "example to watch events happen as you give commands.")
 | 
			
		||||
 | 
			
		||||
    # Setup the PubsubEvents listener
 | 
			
		||||
    xmpp = PubsubEvents(opts.jid, opts.password)
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
    xmpp = PubsubEvents(args.jid, args.password)
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										103
									
								
								examples/register_account.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										103
									
								
								examples/register_account.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,34 +1,23 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RegisterBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class RegisterBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A basic bot that will attempt to register an account
 | 
			
		||||
@@ -40,23 +29,23 @@ class RegisterBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
        # and the XML streams are ready for use. We want to
 | 
			
		||||
        # listen for this event so that we we can initialize
 | 
			
		||||
        # our roster.
 | 
			
		||||
        self.add_event_handler("session_start", self.start, threaded=True)
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
 | 
			
		||||
        # The register event provides an Iq result stanza with
 | 
			
		||||
        # a registration form from the server. This may include
 | 
			
		||||
        # the basic registration fields, a data form, an 
 | 
			
		||||
        # the basic registration fields, a data form, an
 | 
			
		||||
        # out-of-band URL, or any combination. For more advanced
 | 
			
		||||
        # cases, you will need to examine the fields provided
 | 
			
		||||
        # and respond accordingly. SleekXMPP provides plugins
 | 
			
		||||
        # and respond accordingly. Slixmpp provides plugins
 | 
			
		||||
        # for data forms and OOB links that will make that easier.
 | 
			
		||||
        self.add_event_handler("register", self.register, threaded=True)
 | 
			
		||||
        self.add_event_handler("register", self.register)
 | 
			
		||||
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
@@ -101,10 +90,10 @@ class RegisterBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
        resp['register']['password'] = self.password
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            resp.send(now=True)
 | 
			
		||||
            yield from resp.send()
 | 
			
		||||
            logging.info("Account created for %s!" % self.boundjid)
 | 
			
		||||
        except IqError as e:
 | 
			
		||||
            logging.error("Could not register account: %s" % 
 | 
			
		||||
            logging.error("Could not register account: %s" %
 | 
			
		||||
                    e.iq['error']['text'])
 | 
			
		||||
            self.disconnect()
 | 
			
		||||
        except IqTimeout:
 | 
			
		||||
@@ -114,62 +103,46 @@ class RegisterBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the RegisterBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = RegisterBot(opts.jid, opts.password)
 | 
			
		||||
    xmpp = RegisterBot(args.jid, args.password)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data forms
 | 
			
		||||
    xmpp.register_plugin('xep_0066') # Out-of-band Data
 | 
			
		||||
    xmpp.register_plugin('xep_0077') # In-band Registration
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
    # Some servers don't advertise support for inband registration, even
 | 
			
		||||
    # though they allow it. If this applies to your server, use:
 | 
			
		||||
    xmpp['xep_0077'].force_registration = True
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										120
									
								
								examples/roster_browser.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										120
									
								
								examples/roster_browser.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,36 +1,24 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
import threading
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.exceptions import IqError, IqTimeout
 | 
			
		||||
from slixmpp.xmlstream.asyncio import asyncio
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RosterBrowser(sleekxmpp.ClientXMPP):
 | 
			
		||||
class RosterBrowser(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A basic script for dumping a client's roster to
 | 
			
		||||
@@ -38,20 +26,19 @@ class RosterBrowser(sleekxmpp.ClientXMPP):
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
        # the bot establishes its connection with the server
 | 
			
		||||
        # and the XML streams are ready for use. We want to
 | 
			
		||||
        # listen for this event so that we we can initialize
 | 
			
		||||
        # our roster. We need threaded=True so that the
 | 
			
		||||
        # session_start handler doesn't block event processing
 | 
			
		||||
        # while we wait for presence stanzas to arrive.
 | 
			
		||||
        self.add_event_handler("session_start", self.start, threaded=True)
 | 
			
		||||
        # our roster.
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
        self.add_event_handler("changed_status", self.wait_for_presences)
 | 
			
		||||
 | 
			
		||||
        self.received = set()
 | 
			
		||||
        self.presences_received = threading.Event()
 | 
			
		||||
        self.presences_received = asyncio.Event()
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
        Process the session_start event.
 | 
			
		||||
@@ -65,8 +52,12 @@ class RosterBrowser(sleekxmpp.ClientXMPP):
 | 
			
		||||
                     event does not provide any additional
 | 
			
		||||
                     data.
 | 
			
		||||
        """
 | 
			
		||||
        future = asyncio.Future()
 | 
			
		||||
        def callback(result):
 | 
			
		||||
            future.set_result(None)
 | 
			
		||||
        try:
 | 
			
		||||
            self.get_roster()
 | 
			
		||||
            self.get_roster(callback=callback)
 | 
			
		||||
            yield from future
 | 
			
		||||
        except IqError as err:
 | 
			
		||||
            print('Error: %' % err.iq['error']['condition'])
 | 
			
		||||
        except IqTimeout:
 | 
			
		||||
@@ -75,7 +66,7 @@ class RosterBrowser(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        print('Waiting for presence updates...\n')
 | 
			
		||||
        self.presences_received.wait(5)
 | 
			
		||||
        yield from asyncio.sleep(10)
 | 
			
		||||
 | 
			
		||||
        print('Roster for %s' % self.boundjid.bare)
 | 
			
		||||
        groups = self.client_roster.groups()
 | 
			
		||||
@@ -115,58 +106,37 @@ class RosterBrowser(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    optp.add_option('-q','--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-d','--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-v','--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=5,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
    parser.add_argument("-q","--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
    parser.add_argument("-d","--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    opts,args = optp.parse_args()
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    xmpp = RosterBrowser(opts.jid, opts.password)
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
    xmpp = RosterBrowser(args.jid, args.password)
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								examples/rpc_async.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										37
									
								
								examples/rpc_async.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,44 +1,47 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Dann Martens
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0009.remote import Endpoint, remote, Remote, \
 | 
			
		||||
from slixmpp.plugins.xep_0009.remote import Endpoint, remote, Remote, \
 | 
			
		||||
    ANY_ALL, Future
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
class Boomerang(Endpoint):
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def FQN(self):
 | 
			
		||||
        return 'boomerang'
 | 
			
		||||
          
 | 
			
		||||
 | 
			
		||||
    @remote
 | 
			
		||||
    def throw(self):
 | 
			
		||||
        print "Duck!"
 | 
			
		||||
            
 | 
			
		||||
        print("Duck!")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
 | 
			
		||||
    session = Remote.new_session('kangaroo@xmpp.org/rpc', '*****')
 | 
			
		||||
 | 
			
		||||
    session.new_handler(ANY_ALL, Boomerang)    
 | 
			
		||||
    
 | 
			
		||||
    session.new_handler(ANY_ALL, Boomerang)
 | 
			
		||||
 | 
			
		||||
    boomerang = session.new_proxy('kangaroo@xmpp.org/rpc', Boomerang)
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    callback = Future()
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
    boomerang.async(callback).throw()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    time.sleep(10)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    session.close()
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								examples/rpc_client_side.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										35
									
								
								examples/rpc_client_side.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,29 +1,32 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Dann Martens
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0009.remote import Endpoint, remote, Remote, \
 | 
			
		||||
from slixmpp.plugins.xep_0009.remote import Endpoint, remote, Remote, \
 | 
			
		||||
    ANY_ALL
 | 
			
		||||
import threading
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
class Thermostat(Endpoint):
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def FQN(self):
 | 
			
		||||
        return 'thermostat'
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def __init__(self, initial_temperature):
 | 
			
		||||
        self._temperature = initial_temperature
 | 
			
		||||
        self._event = threading.Event()        
 | 
			
		||||
    
 | 
			
		||||
        self._event = threading.Event()
 | 
			
		||||
 | 
			
		||||
    @remote
 | 
			
		||||
    def set_temperature(self, temperature):
 | 
			
		||||
        return NotImplemented
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    @remote
 | 
			
		||||
    def get_temperature(self):
 | 
			
		||||
        return NotImplemented
 | 
			
		||||
@@ -31,23 +34,23 @@ class Thermostat(Endpoint):
 | 
			
		||||
    @remote(False)
 | 
			
		||||
    def release(self):
 | 
			
		||||
        return NotImplemented
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
 | 
			
		||||
    session = Remote.new_session('operator@xmpp.org/rpc', '*****')
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    thermostat = session.new_proxy('thermostat@xmpp.org/rpc', Thermostat)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    print("Current temperature is %s" % thermostat.get_temperature())
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    thermostat.set_temperature(20)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    time.sleep(10)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    session.close()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								examples/rpc_server_side.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										37
									
								
								examples/rpc_server_side.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,52 +1,55 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Dann Martens
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0009.remote import Endpoint, remote, Remote, \
 | 
			
		||||
from slixmpp.plugins.xep_0009.remote import Endpoint, remote, Remote, \
 | 
			
		||||
    ANY_ALL
 | 
			
		||||
import threading
 | 
			
		||||
 | 
			
		||||
class Thermostat(Endpoint):
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def FQN(self):
 | 
			
		||||
        return 'thermostat'
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    def __init__(self, initial_temperature):
 | 
			
		||||
        self._temperature = initial_temperature
 | 
			
		||||
        self._event = threading.Event()        
 | 
			
		||||
    
 | 
			
		||||
        self._event = threading.Event()
 | 
			
		||||
 | 
			
		||||
    @remote
 | 
			
		||||
    def set_temperature(self, temperature):
 | 
			
		||||
        print("Setting temperature to %s" % temperature)
 | 
			
		||||
        self._temperature = temperature
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    @remote
 | 
			
		||||
    def get_temperature(self):
 | 
			
		||||
        return self._temperature
 | 
			
		||||
 | 
			
		||||
    @remote(False)
 | 
			
		||||
    def release(self):
 | 
			
		||||
        self._event.set() 
 | 
			
		||||
        
 | 
			
		||||
        self._event.set()
 | 
			
		||||
 | 
			
		||||
    def wait_for_release(self):
 | 
			
		||||
        self._event.wait()        
 | 
			
		||||
    
 | 
			
		||||
        self._event.wait()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
 | 
			
		||||
    session = Remote.new_session('sleek@xmpp.org/rpc', '*****')
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    thermostat = session.new_handler(ANY_ALL, Thermostat, 18)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    thermostat.wait_for_release()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    session.close()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,41 +1,30 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class SendMsgBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class SendMsgBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A basic SleekXMPP bot that will log in, send a message,
 | 
			
		||||
    A basic Slixmpp bot that will log in, send a message,
 | 
			
		||||
    and then log out.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, recipient, message):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # The message we wish to send, and the JID that
 | 
			
		||||
        # will receive it.
 | 
			
		||||
@@ -47,7 +36,7 @@ class SendMsgBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
        # and the XML streams are ready for use. We want to
 | 
			
		||||
        # listen for this event so that we we can initialize
 | 
			
		||||
        # our roster.
 | 
			
		||||
        self.add_event_handler("session_start", self.start, threaded=True)
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
@@ -69,75 +58,53 @@ class SendMsgBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
                          mbody=self.msg,
 | 
			
		||||
                          mtype='chat')
 | 
			
		||||
 | 
			
		||||
        # Using wait=True ensures that the send queue will be
 | 
			
		||||
        # emptied before ending the session.
 | 
			
		||||
        self.disconnect(wait=True)
 | 
			
		||||
        self.disconnect()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser(description=SendMsgBot.__doc__)
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("-t", "--to", dest="to",
 | 
			
		||||
                    help="JID to send the message to")
 | 
			
		||||
    optp.add_option("-m", "--message", dest="message",
 | 
			
		||||
                    help="message to send")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-t", "--to", dest="to",
 | 
			
		||||
                        help="JID to send the message to")
 | 
			
		||||
    parser.add_argument("-m", "--message", dest="message",
 | 
			
		||||
                        help="message to send")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.to is None:
 | 
			
		||||
        opts.to = raw_input("Send To: ")
 | 
			
		||||
    if opts.message is None:
 | 
			
		||||
        opts.message = raw_input("Message: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.to is None:
 | 
			
		||||
        args.to = input("Send To: ")
 | 
			
		||||
    if args.message is None:
 | 
			
		||||
        args.message = input("Message: ")
 | 
			
		||||
 | 
			
		||||
    # Setup the EchoBot and register plugins. Note that while plugins may
 | 
			
		||||
    # have interdependencies, the order in which you register them does
 | 
			
		||||
    # not matter.
 | 
			
		||||
    xmpp = SendMsgBot(opts.jid, opts.password, opts.to, opts.message)
 | 
			
		||||
    xmpp = SendMsgBot(args.jid, args.password, args.to, args.message)
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0199') # XMPP Ping
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										158
									
								
								examples/set_avatar.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										158
									
								
								examples/set_avatar.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,50 +1,39 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2012  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
import sys
 | 
			
		||||
import imghdr
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
import threading
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.exceptions import XMPPError
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.exceptions import XMPPError
 | 
			
		||||
from slixmpp import asyncio
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AvatarSetter(sleekxmpp.ClientXMPP):
 | 
			
		||||
class AvatarSetter(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A basic script for downloading the avatars for a user's contacts.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password, filepath):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        self.add_event_handler("session_start", self.start, threaded=True)
 | 
			
		||||
        self.add_event_handler("session_start", self.start)
 | 
			
		||||
 | 
			
		||||
        self.filepath = filepath
 | 
			
		||||
 | 
			
		||||
    @asyncio.coroutine
 | 
			
		||||
    def start(self, event):
 | 
			
		||||
        """
 | 
			
		||||
        Process the session_start event.
 | 
			
		||||
@@ -63,7 +52,7 @@ class AvatarSetter(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
        avatar_file = None
 | 
			
		||||
        try:
 | 
			
		||||
            avatar_file = open(os.path.expanduser(self.filepath))
 | 
			
		||||
            avatar_file = open(os.path.expanduser(self.filepath), 'rb')
 | 
			
		||||
        except IOError:
 | 
			
		||||
            print('Could not find file: %s' % self.filepath)
 | 
			
		||||
            return self.disconnect()
 | 
			
		||||
@@ -77,32 +66,31 @@ class AvatarSetter(sleekxmpp.ClientXMPP):
 | 
			
		||||
        avatar_file.close()
 | 
			
		||||
 | 
			
		||||
        used_xep84 = False
 | 
			
		||||
        try:
 | 
			
		||||
            print('Publish XEP-0084 avatar data')
 | 
			
		||||
            self['xep_0084'].publish_avatar(avatar)
 | 
			
		||||
            used_xep84 = True
 | 
			
		||||
        except XMPPError:
 | 
			
		||||
            print('Could not publish XEP-0084 avatar')
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            print('Update vCard with avatar')
 | 
			
		||||
            self['xep_0153'].set_avatar(avatar=avatar, mtype=avatar_type)
 | 
			
		||||
        except XMPPError:
 | 
			
		||||
        print('Publish XEP-0084 avatar data')
 | 
			
		||||
        result = yield from self['xep_0084'].publish_avatar(avatar)
 | 
			
		||||
        if isinstance(result, XMPPError):
 | 
			
		||||
            print('Could not publish XEP-0084 avatar')
 | 
			
		||||
        else:
 | 
			
		||||
            used_xep84 = True
 | 
			
		||||
 | 
			
		||||
        print('Update vCard with avatar')
 | 
			
		||||
        result = yield from self['xep_0153'].set_avatar(avatar=avatar, mtype=avatar_type)
 | 
			
		||||
        if isinstance(result, XMPPError):
 | 
			
		||||
            print('Could not set vCard avatar')
 | 
			
		||||
 | 
			
		||||
        if used_xep84:
 | 
			
		||||
            try:
 | 
			
		||||
                print('Advertise XEP-0084 avatar metadata')
 | 
			
		||||
                self['xep_0084'].publish_avatar_metadata([
 | 
			
		||||
                    {'id': avatar_id,
 | 
			
		||||
                     'type': avatar_type,
 | 
			
		||||
                     'bytes': avatar_bytes}
 | 
			
		||||
                    # We could advertise multiple avatars to provide
 | 
			
		||||
                    # options in image type, source (HTTP vs pubsub),
 | 
			
		||||
                    # size, etc.
 | 
			
		||||
                    # {'id': ....}
 | 
			
		||||
                ])
 | 
			
		||||
            except XMPPError:
 | 
			
		||||
            print('Advertise XEP-0084 avatar metadata')
 | 
			
		||||
            result = yield from self['xep_0084'].publish_avatar_metadata([
 | 
			
		||||
                {'id': avatar_id,
 | 
			
		||||
                 'type': avatar_type,
 | 
			
		||||
                 'bytes': avatar_bytes}
 | 
			
		||||
                # We could advertise multiple avatars to provide
 | 
			
		||||
                # options in image type, source (HTTP vs pubsub),
 | 
			
		||||
                # size, etc.
 | 
			
		||||
                # {'id': ....}
 | 
			
		||||
            ])
 | 
			
		||||
            if isinstance(result, XMPPError):
 | 
			
		||||
                print('Could not publish XEP-0084 metadata')
 | 
			
		||||
 | 
			
		||||
        print('Wait for presence updates to propagate...')
 | 
			
		||||
@@ -111,64 +99,44 @@ class AvatarSetter(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    optp.add_option('-q','--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-d','--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    optp.add_option('-v','--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const',
 | 
			
		||||
                    dest='loglevel',
 | 
			
		||||
                    const=5,
 | 
			
		||||
                    default=logging.ERROR)
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
    parser.add_argument("-q","--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
    parser.add_argument("-d","--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const",
 | 
			
		||||
                        dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG,
 | 
			
		||||
                        default=logging.ERROR)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    optp.add_option("-f", "--file", dest="filepath",
 | 
			
		||||
                    help="path to the avatar file")
 | 
			
		||||
    opts,args = optp.parse_args()
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
    parser.add_argument("-f", "--file", dest="filepath",
 | 
			
		||||
                        help="path to the avatar file")
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if opts.filepath is None:
 | 
			
		||||
        opts.filepath = raw_input("Avatar file location: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
    if args.filepath is None:
 | 
			
		||||
        args.filepath = input("Avatar file location: ")
 | 
			
		||||
 | 
			
		||||
    xmpp = AvatarSetter(opts.jid, opts.password, opts.filepath)
 | 
			
		||||
    xmpp = AvatarSetter(args.jid, args.password, args.filepath)
 | 
			
		||||
    xmpp.register_plugin('xep_0054')
 | 
			
		||||
    xmpp.register_plugin('xep_0153')
 | 
			
		||||
    xmpp.register_plugin('xep_0084')
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										97
									
								
								examples/thirdparty_auth.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										97
									
								
								examples/thirdparty_auth.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,18 +1,18 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Slixmpp: The Slick XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    This file is part of Slixmpp.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from httplib import HTTPSConnection
 | 
			
		||||
@@ -21,24 +21,14 @@ except ImportError:
 | 
			
		||||
    from urllib.parse import urlencode
 | 
			
		||||
    from http.client import HTTPSConnection
 | 
			
		||||
 | 
			
		||||
import sleekxmpp
 | 
			
		||||
from sleekxmpp.xmlstream import JID
 | 
			
		||||
 | 
			
		||||
# Python versions before 3.0 do not use UTF-8 encoding
 | 
			
		||||
# by default. To ensure that Unicode is handled properly
 | 
			
		||||
# throughout SleekXMPP, we will set the default encoding
 | 
			
		||||
# ourselves to UTF-8.
 | 
			
		||||
if sys.version_info < (3, 0):
 | 
			
		||||
    from sleekxmpp.util.misc_ops import setdefaultencoding
 | 
			
		||||
    setdefaultencoding('utf8')
 | 
			
		||||
else:
 | 
			
		||||
    raw_input = input
 | 
			
		||||
import slixmpp
 | 
			
		||||
from slixmpp.xmlstream import JID
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ThirdPartyAuthBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
class ThirdPartyAuthBot(slixmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A simple SleekXMPP bot that will echo messages it
 | 
			
		||||
    A simple Slixmpp bot that will echo messages it
 | 
			
		||||
    receives, along with a short thank you message.
 | 
			
		||||
 | 
			
		||||
    This version uses a thirdpary service for authentication,
 | 
			
		||||
@@ -46,7 +36,7 @@ class ThirdPartyAuthBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        sleekxmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
        slixmpp.ClientXMPP.__init__(self, jid, password)
 | 
			
		||||
 | 
			
		||||
        # The X-GOOGLE-TOKEN mech is ranked lower than PLAIN
 | 
			
		||||
        # due to Google only allowing a single SASL attempt per
 | 
			
		||||
@@ -55,7 +45,7 @@ class ThirdPartyAuthBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
        # X-GOOGLE-TOKEN with a TLS connection, explicitly select
 | 
			
		||||
        # it using:
 | 
			
		||||
        #
 | 
			
		||||
        # sleekxmpp.ClientXMPP.__init__(self, jid, password,
 | 
			
		||||
        # slixmpp.ClientXMPP.__init__(self, jid, password,
 | 
			
		||||
        #                               sasl_mech="X-GOOGLE-TOKEN")
 | 
			
		||||
 | 
			
		||||
        # The session_start event will be triggered when
 | 
			
		||||
@@ -104,37 +94,34 @@ class ThirdPartyAuthBot(sleekxmpp.ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    access_token = None
 | 
			
		||||
 | 
			
		||||
    # Since documentation on how to work with Google tokens
 | 
			
		||||
@@ -156,11 +143,11 @@ if __name__ == '__main__':
 | 
			
		||||
    params = urlencode({
 | 
			
		||||
        'accountType': 'GOOGLE',
 | 
			
		||||
        'service': 'mail',
 | 
			
		||||
        'Email': JID(opts.jid).bare,
 | 
			
		||||
        'Passwd': opts.password
 | 
			
		||||
        'Email': JID(args.jid).bare,
 | 
			
		||||
        'Passwd': args.password
 | 
			
		||||
    })
 | 
			
		||||
    headers = {
 | 
			
		||||
        'Content-Type': 'application/x-www-form-urlencoded' 
 | 
			
		||||
        'Content-Type': 'application/x-www-form-urlencoded'
 | 
			
		||||
    }
 | 
			
		||||
    try:
 | 
			
		||||
        conn.request('POST', '/accounts/ClientLogin', params, headers)
 | 
			
		||||
@@ -208,12 +195,12 @@ if __name__ == '__main__':
 | 
			
		||||
    # We're using an access token instead of a password, so we'll use `''` as
 | 
			
		||||
    # a password argument filler.
 | 
			
		||||
 | 
			
		||||
    xmpp = ThirdPartyAuthBot(opts.jid, '')  
 | 
			
		||||
    xmpp = ThirdPartyAuthBot(args.jid, '')
 | 
			
		||||
    xmpp.credentials['access_token'] = access_token
 | 
			
		||||
 | 
			
		||||
    # The credentials dictionary is used to provide additional authentication
 | 
			
		||||
    # information beyond just a password.
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    xmpp.register_plugin('xep_0030') # Service Discovery
 | 
			
		||||
    xmpp.register_plugin('xep_0004') # Data Forms
 | 
			
		||||
    xmpp.register_plugin('xep_0060') # PubSub
 | 
			
		||||
@@ -231,17 +218,7 @@ if __name__ == '__main__':
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    # Google only allows one SASL attempt per connection, so in order to 
 | 
			
		||||
    # Google only allows one SASL attempt per connection, so in order to
 | 
			
		||||
    # enable the X-GOOGLE-TOKEN mechanism, we'll disable TLS.
 | 
			
		||||
    if xmpp.connect(use_tls=False):
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										72
									
								
								examples/user_location.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										72
									
								
								examples/user_location.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,9 +1,9 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    import json
 | 
			
		||||
@@ -16,7 +16,7 @@ except ImportError:
 | 
			
		||||
    print('This demo requires the requests package for using HTTP.')
 | 
			
		||||
    sys.exit()
 | 
			
		||||
 | 
			
		||||
from sleekxmpp import ClientXMPP
 | 
			
		||||
from slixmpp import ClientXMPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LocationBot(ClientXMPP):
 | 
			
		||||
@@ -24,8 +24,8 @@ class LocationBot(ClientXMPP):
 | 
			
		||||
    def __init__(self, jid, password):
 | 
			
		||||
        super(LocationBot, self).__init__(jid, password)
 | 
			
		||||
 | 
			
		||||
        self.add_event_handler('session_start', self.start, threaded=True)
 | 
			
		||||
        self.add_event_handler('user_location_publish', 
 | 
			
		||||
        self.add_event_handler('session_start', self.start)
 | 
			
		||||
        self.add_event_handler('user_location_publish',
 | 
			
		||||
                               self.user_location_publish)
 | 
			
		||||
 | 
			
		||||
        self.register_plugin('xep_0004')
 | 
			
		||||
@@ -71,55 +71,35 @@ class LocationBot(ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    xmpp = LocationBot(opts.jid, opts.password)
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
    xmpp = LocationBot(args.jid, args.password)
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										68
									
								
								examples/user_tune.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										68
									
								
								examples/user_tune.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -1,9 +1,9 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import getpass
 | 
			
		||||
from optparse import OptionParser
 | 
			
		||||
from getpass import getpass
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    from appscript import *
 | 
			
		||||
@@ -11,7 +11,7 @@ except ImportError:
 | 
			
		||||
    print('This demo requires the appscript package to interact with iTunes.')
 | 
			
		||||
    sys.exit()
 | 
			
		||||
 | 
			
		||||
from sleekxmpp import ClientXMPP
 | 
			
		||||
from slixmpp import ClientXMPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TuneBot(ClientXMPP):
 | 
			
		||||
@@ -83,55 +83,35 @@ class TuneBot(ClientXMPP):
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    # Setup the command line arguments.
 | 
			
		||||
    optp = OptionParser()
 | 
			
		||||
    parser = ArgumentParser()
 | 
			
		||||
 | 
			
		||||
    # Output verbosity options.
 | 
			
		||||
    optp.add_option('-q', '--quiet', help='set logging to ERROR',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-d', '--debug', help='set logging to DEBUG',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
    optp.add_option('-v', '--verbose', help='set logging to COMM',
 | 
			
		||||
                    action='store_const', dest='loglevel',
 | 
			
		||||
                    const=5, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-q", "--quiet", help="set logging to ERROR",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.ERROR, default=logging.INFO)
 | 
			
		||||
    parser.add_argument("-d", "--debug", help="set logging to DEBUG",
 | 
			
		||||
                        action="store_const", dest="loglevel",
 | 
			
		||||
                        const=logging.DEBUG, default=logging.INFO)
 | 
			
		||||
 | 
			
		||||
    # JID and password options.
 | 
			
		||||
    optp.add_option("-j", "--jid", dest="jid",
 | 
			
		||||
                    help="JID to use")
 | 
			
		||||
    optp.add_option("-p", "--password", dest="password",
 | 
			
		||||
                    help="password to use")
 | 
			
		||||
    parser.add_argument("-j", "--jid", dest="jid",
 | 
			
		||||
                        help="JID to use")
 | 
			
		||||
    parser.add_argument("-p", "--password", dest="password",
 | 
			
		||||
                        help="password to use")
 | 
			
		||||
 | 
			
		||||
    opts, args = optp.parse_args()
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    # Setup logging.
 | 
			
		||||
    logging.basicConfig(level=opts.loglevel,
 | 
			
		||||
    logging.basicConfig(level=args.loglevel,
 | 
			
		||||
                        format='%(levelname)-8s %(message)s')
 | 
			
		||||
 | 
			
		||||
    if opts.jid is None:
 | 
			
		||||
        opts.jid = raw_input("Username: ")
 | 
			
		||||
    if opts.password is None:
 | 
			
		||||
        opts.password = getpass.getpass("Password: ")
 | 
			
		||||
    if args.jid is None:
 | 
			
		||||
        args.jid = input("Username: ")
 | 
			
		||||
    if args.password is None:
 | 
			
		||||
        args.password = getpass("Password: ")
 | 
			
		||||
 | 
			
		||||
    xmpp = TuneBot(opts.jid, opts.password)
 | 
			
		||||
 | 
			
		||||
    # If you are working with an OpenFire server, you may need
 | 
			
		||||
    # to adjust the SSL version used:
 | 
			
		||||
    # xmpp.ssl_version = ssl.PROTOCOL_SSLv3
 | 
			
		||||
 | 
			
		||||
    # If you want to verify the SSL certificates offered by a server:
 | 
			
		||||
    # xmpp.ca_certs = "path/to/ca/cert"
 | 
			
		||||
    xmpp = TuneBot(args.jid, args.password)
 | 
			
		||||
 | 
			
		||||
    # Connect to the XMPP server and start processing XMPP stanzas.
 | 
			
		||||
    if xmpp.connect():
 | 
			
		||||
        # If you do not have the dnspython library installed, you will need
 | 
			
		||||
        # to manually specify the name of the server if it does not match
 | 
			
		||||
        # the one in the JID. For example, to use Google Talk you would
 | 
			
		||||
        # need to use:
 | 
			
		||||
        #
 | 
			
		||||
        # if xmpp.connect(('talk.google.com', 5222)):
 | 
			
		||||
        #     ...
 | 
			
		||||
        xmpp.process(block=True)
 | 
			
		||||
        print("Done")
 | 
			
		||||
    else:
 | 
			
		||||
        print("Unable to connect.")
 | 
			
		||||
    xmpp.connect()
 | 
			
		||||
    xmpp.process()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										233
									
								
								ez_setup.py
									
									
									
									
									
								
							
							
						
						
									
										233
									
								
								ez_setup.py
									
									
									
									
									
								
							@@ -1,233 +0,0 @@
 | 
			
		||||
#!python
 | 
			
		||||
"""Bootstrap setuptools installation
 | 
			
		||||
 | 
			
		||||
If you want to use setuptools in your package's setup.py, just include this
 | 
			
		||||
file in the same directory with it, and add this to the top of your setup.py::
 | 
			
		||||
 | 
			
		||||
    from ez_setup import use_setuptools
 | 
			
		||||
    use_setuptools()
 | 
			
		||||
 | 
			
		||||
If you want to require a specific version of setuptools, set a download
 | 
			
		||||
mirror, or use an alternate download directory, you can do so by supplying
 | 
			
		||||
the appropriate options to ``use_setuptools()``.
 | 
			
		||||
 | 
			
		||||
This file can also be run as a script to install or upgrade setuptools.
 | 
			
		||||
"""
 | 
			
		||||
import sys
 | 
			
		||||
DEFAULT_VERSION = "0.6c7"
 | 
			
		||||
DEFAULT_URL     = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
 | 
			
		||||
 | 
			
		||||
md5_data = {
 | 
			
		||||
    'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
 | 
			
		||||
    'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
 | 
			
		||||
    'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
 | 
			
		||||
    'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
 | 
			
		||||
    'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
 | 
			
		||||
    'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
 | 
			
		||||
    'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
 | 
			
		||||
    'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
 | 
			
		||||
    'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
 | 
			
		||||
    'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
 | 
			
		||||
    'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
 | 
			
		||||
    'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
 | 
			
		||||
    'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
 | 
			
		||||
    'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
 | 
			
		||||
    'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
 | 
			
		||||
    'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
 | 
			
		||||
    'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
 | 
			
		||||
    'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
 | 
			
		||||
    'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
 | 
			
		||||
    'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
 | 
			
		||||
    'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
 | 
			
		||||
    'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
 | 
			
		||||
    'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
 | 
			
		||||
    'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
import sys, os
 | 
			
		||||
 | 
			
		||||
def _validate_md5(egg_name, data):
 | 
			
		||||
    if egg_name in md5_data:
 | 
			
		||||
        from md5 import md5
 | 
			
		||||
        digest = md5(data).hexdigest()
 | 
			
		||||
        if digest != md5_data[egg_name]:
 | 
			
		||||
            print >>sys.stderr, (
 | 
			
		||||
                "md5 validation of %s failed!  (Possible download problem?)"
 | 
			
		||||
                % egg_name
 | 
			
		||||
            )
 | 
			
		||||
            sys.exit(2)
 | 
			
		||||
    return data
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def use_setuptools(
 | 
			
		||||
    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir, min_version=None,
 | 
			
		||||
    download_delay=15
 | 
			
		||||
):
 | 
			
		||||
    """Automatically find/download setuptools and make it available on sys.path
 | 
			
		||||
 | 
			
		||||
    `version` should be a valid setuptools version number that is available
 | 
			
		||||
    as an egg for download under the `download_base` URL (which should end with
 | 
			
		||||
    a '/').  `to_dir` is the directory where setuptools will be downloaded, if
 | 
			
		||||
    it is not already available.  If `download_delay` is specified, it should
 | 
			
		||||
    be the number of seconds that will be paused before initiating a download,
 | 
			
		||||
    should one be required.  If an older version of setuptools is installed,
 | 
			
		||||
    this routine will print a message to ``sys.stderr`` and raise SystemExit in
 | 
			
		||||
    an attempt to abort the calling script.
 | 
			
		||||
    """
 | 
			
		||||
    try:
 | 
			
		||||
        import setuptools
 | 
			
		||||
        if setuptools.__version__ == '0.0.1':
 | 
			
		||||
            print >>sys.stderr, (
 | 
			
		||||
            "You have an obsolete version of setuptools installed.  Please\n"
 | 
			
		||||
            "remove it from your system entirely before rerunning this script."
 | 
			
		||||
            )
 | 
			
		||||
            sys.exit(2)
 | 
			
		||||
    except ImportError:
 | 
			
		||||
        egg = download_setuptools(version, download_base, to_dir, download_delay)
 | 
			
		||||
        sys.path.insert(0, egg)
 | 
			
		||||
        import setuptools; setuptools.bootstrap_install_from = egg
 | 
			
		||||
 | 
			
		||||
    import pkg_resources
 | 
			
		||||
    try:
 | 
			
		||||
        if not min_version:
 | 
			
		||||
            min_version = version
 | 
			
		||||
        pkg_resources.require("setuptools>="+min_version)
 | 
			
		||||
 | 
			
		||||
    except pkg_resources.VersionConflict, e:
 | 
			
		||||
        # XXX could we install in a subprocess here?
 | 
			
		||||
        print >>sys.stderr, (
 | 
			
		||||
            "The required version of setuptools (>=%s) is not available, and\n"
 | 
			
		||||
            "can't be installed while this script is running. Please install\n"
 | 
			
		||||
            " a more recent version first.\n\n(Currently using %r)"
 | 
			
		||||
        ) % (min_version, e.args[0])
 | 
			
		||||
        sys.exit(2)
 | 
			
		||||
 | 
			
		||||
def download_setuptools(
 | 
			
		||||
    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
 | 
			
		||||
    delay = 15
 | 
			
		||||
):
 | 
			
		||||
    """Download setuptools from a specified location and return its filename
 | 
			
		||||
 | 
			
		||||
    `version` should be a valid setuptools version number that is available
 | 
			
		||||
    as an egg for download under the `download_base` URL (which should end
 | 
			
		||||
    with a '/'). `to_dir` is the directory where the egg will be downloaded.
 | 
			
		||||
    `delay` is the number of seconds to pause before an actual download attempt.
 | 
			
		||||
    """
 | 
			
		||||
    import urllib2, shutil
 | 
			
		||||
    egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
 | 
			
		||||
    url = download_base + egg_name
 | 
			
		||||
    saveto = os.path.join(to_dir, egg_name)
 | 
			
		||||
    src = dst = None
 | 
			
		||||
    if not os.path.exists(saveto):  # Avoid repeated downloads
 | 
			
		||||
        try:
 | 
			
		||||
            from distutils import log
 | 
			
		||||
            if delay:
 | 
			
		||||
                log.warn("""
 | 
			
		||||
---------------------------------------------------------------------------
 | 
			
		||||
This script requires setuptools version %s to run (even to display
 | 
			
		||||
help).  I will attempt to download it for you (from
 | 
			
		||||
%s), but
 | 
			
		||||
you may need to enable firewall access for this script first.
 | 
			
		||||
I will start the download in %d seconds.
 | 
			
		||||
 | 
			
		||||
(Note: if this machine does not have network access, please obtain the file
 | 
			
		||||
 | 
			
		||||
   %s
 | 
			
		||||
 | 
			
		||||
and place it in this directory before rerunning this script.)
 | 
			
		||||
---------------------------------------------------------------------------""",
 | 
			
		||||
                    version, download_base, delay, url
 | 
			
		||||
                ); from time import sleep; sleep(delay)
 | 
			
		||||
            log.warn("Downloading %s", url)
 | 
			
		||||
            src = urllib2.urlopen(url)
 | 
			
		||||
            # Read/write all in one block, so we don't create a corrupt file
 | 
			
		||||
            # if the download is interrupted.
 | 
			
		||||
            data = _validate_md5(egg_name, src.read())
 | 
			
		||||
            dst = open(saveto,"wb"); dst.write(data)
 | 
			
		||||
        finally:
 | 
			
		||||
            if src: src.close()
 | 
			
		||||
            if dst: dst.close()
 | 
			
		||||
    return os.path.realpath(saveto)
 | 
			
		||||
 | 
			
		||||
def main(argv, version=DEFAULT_VERSION):
 | 
			
		||||
    """Install or upgrade setuptools and EasyInstall"""
 | 
			
		||||
 | 
			
		||||
    try:
 | 
			
		||||
        import setuptools
 | 
			
		||||
    except ImportError:
 | 
			
		||||
        egg = None
 | 
			
		||||
        try:
 | 
			
		||||
            egg = download_setuptools(version, delay=0)
 | 
			
		||||
            sys.path.insert(0,egg)
 | 
			
		||||
            from setuptools.command.easy_install import main
 | 
			
		||||
            return main(list(argv)+[egg])   # we're done here
 | 
			
		||||
        finally:
 | 
			
		||||
            if egg and os.path.exists(egg):
 | 
			
		||||
                os.unlink(egg)
 | 
			
		||||
    else:
 | 
			
		||||
        if setuptools.__version__ == '0.0.1':
 | 
			
		||||
            # tell the user to uninstall obsolete version
 | 
			
		||||
            use_setuptools(version)
 | 
			
		||||
 | 
			
		||||
    req = "setuptools>="+version
 | 
			
		||||
    import pkg_resources
 | 
			
		||||
    try:
 | 
			
		||||
        pkg_resources.require(req)
 | 
			
		||||
    except pkg_resources.VersionConflict:
 | 
			
		||||
        try:
 | 
			
		||||
            from setuptools.command.easy_install import main
 | 
			
		||||
        except ImportError:
 | 
			
		||||
            from easy_install import main
 | 
			
		||||
        main(list(argv)+[download_setuptools(delay=0)])
 | 
			
		||||
        sys.exit(0) # try to force an exit
 | 
			
		||||
    else:
 | 
			
		||||
        if argv:
 | 
			
		||||
            from setuptools.command.easy_install import main
 | 
			
		||||
            main(argv)
 | 
			
		||||
        else:
 | 
			
		||||
            print "Setuptools version",version,"or greater has been installed."
 | 
			
		||||
            print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def update_md5(filenames):
 | 
			
		||||
    """Update our built-in md5 registry"""
 | 
			
		||||
 | 
			
		||||
    import re
 | 
			
		||||
    from md5 import md5
 | 
			
		||||
 | 
			
		||||
    for name in filenames:
 | 
			
		||||
        base = os.path.basename(name)
 | 
			
		||||
        f = open(name,'rb')
 | 
			
		||||
        md5_data[base] = md5(f.read()).hexdigest()
 | 
			
		||||
        f.close()
 | 
			
		||||
 | 
			
		||||
    data = ["    %r: %r,\n" % it for it in md5_data.items()]
 | 
			
		||||
    data.sort()
 | 
			
		||||
    repl = "".join(data)
 | 
			
		||||
 | 
			
		||||
    import inspect
 | 
			
		||||
    srcfile = inspect.getsourcefile(sys.modules[__name__])
 | 
			
		||||
    f = open(srcfile, 'rb'); src = f.read(); f.close()
 | 
			
		||||
 | 
			
		||||
    match = re.search("\nmd5_data = {\n([^}]+)}", src)
 | 
			
		||||
    if not match:
 | 
			
		||||
        print >>sys.stderr, "Internal error!"
 | 
			
		||||
        sys.exit(2)
 | 
			
		||||
 | 
			
		||||
    src = src[:match.start(1)] + repl + src[match.end(1):]
 | 
			
		||||
    f = open(srcfile,'w')
 | 
			
		||||
    f.write(src)
 | 
			
		||||
    f.close()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__=='__main__':
 | 
			
		||||
    if len(sys.argv)>2 and sys.argv[1]=='--md5update':
 | 
			
		||||
        update_md5(sys.argv[2:])
 | 
			
		||||
    else:
 | 
			
		||||
        main(sys.argv[1:])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										69
									
								
								run_tests.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										69
									
								
								run_tests.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import logging
 | 
			
		||||
import unittest
 | 
			
		||||
 | 
			
		||||
from argparse import ArgumentParser
 | 
			
		||||
from distutils.core import Command
 | 
			
		||||
from importlib import import_module
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run_tests(filenames=None):
 | 
			
		||||
    """
 | 
			
		||||
    Find and run all tests in the tests/ directory.
 | 
			
		||||
 | 
			
		||||
    Excludes live tests (tests/live_*).
 | 
			
		||||
    """
 | 
			
		||||
    if not filenames:
 | 
			
		||||
        filenames = [i for i in Path('tests').glob('test_*')]
 | 
			
		||||
    else:
 | 
			
		||||
        filenames = [Path(i) for i in filenames]
 | 
			
		||||
 | 
			
		||||
    modules = ['.'.join(test.parts[:-1] + (test.stem,)) for test in filenames]
 | 
			
		||||
 | 
			
		||||
    suites = []
 | 
			
		||||
    for filename in modules:
 | 
			
		||||
        module = import_module(filename)
 | 
			
		||||
        suites.append(module.suite)
 | 
			
		||||
 | 
			
		||||
    tests = unittest.TestSuite(suites)
 | 
			
		||||
    runner = unittest.TextTestRunner(verbosity=2)
 | 
			
		||||
 | 
			
		||||
    # Disable logging output
 | 
			
		||||
    logging.basicConfig(level=100)
 | 
			
		||||
    logging.disable(100)
 | 
			
		||||
 | 
			
		||||
    result = runner.run(tests)
 | 
			
		||||
    return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Add a 'test' command for setup.py
 | 
			
		||||
 | 
			
		||||
class TestCommand(Command):
 | 
			
		||||
 | 
			
		||||
    user_options = []
 | 
			
		||||
 | 
			
		||||
    def initialize_options(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def finalize_options(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def run(self):
 | 
			
		||||
        run_tests()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    parser = ArgumentParser(description='Run unit tests.')
 | 
			
		||||
    parser.add_argument('tests', metavar='TEST', nargs='*', help='list of tests to run, or nothing to run them all')
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    result = run_tests(args.tests)
 | 
			
		||||
    print("<tests %s ran='%s' errors='%s' fails='%s' success='%s'/>" % (
 | 
			
		||||
        "xmlns='http//andyet.net/protocol/tests'",
 | 
			
		||||
        result.testsRun, len(result.errors),
 | 
			
		||||
        len(result.failures), result.wasSuccessful()))
 | 
			
		||||
 | 
			
		||||
    sys.exit(not result.wasSuccessful())
 | 
			
		||||
							
								
								
									
										161
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										161
									
								
								setup.py
									
									
									
									
									
								
							@@ -1,4 +1,4 @@
 | 
			
		||||
#!/usr/bin/env python
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2007-2011 Nathanael C. Fritz
 | 
			
		||||
@@ -7,131 +7,52 @@
 | 
			
		||||
# This software is licensed as described in the README.rst and LICENSE
 | 
			
		||||
# file, which you should have received as part of this distribution.
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
import codecs
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
try:
 | 
			
		||||
    from setuptools import setup, Command
 | 
			
		||||
    from setuptools import setup
 | 
			
		||||
except ImportError:
 | 
			
		||||
    from distutils.core import setup, Command
 | 
			
		||||
# from ez_setup import use_setuptools
 | 
			
		||||
    from distutils.core import setup
 | 
			
		||||
 | 
			
		||||
from testall import TestCommand
 | 
			
		||||
from sleekxmpp.version import __version__
 | 
			
		||||
# if 'cygwin' in sys.platform.lower():
 | 
			
		||||
#     min_version = '0.6c6'
 | 
			
		||||
# else:
 | 
			
		||||
#     min_version = '0.6a9'
 | 
			
		||||
#
 | 
			
		||||
# try:
 | 
			
		||||
#     use_setuptools(min_version=min_version)
 | 
			
		||||
# except TypeError:
 | 
			
		||||
#     # locally installed ez_setup won't have min_version
 | 
			
		||||
#     use_setuptools()
 | 
			
		||||
#
 | 
			
		||||
# from setuptools import setup, find_packages, Extension, Feature
 | 
			
		||||
try:
 | 
			
		||||
    from Cython.Build import cythonize
 | 
			
		||||
except ImportError:
 | 
			
		||||
    print('Cython not found, falling back to the slow stringprep module.')
 | 
			
		||||
    ext_modules = None
 | 
			
		||||
else:
 | 
			
		||||
    ext_modules = cythonize('slixmpp/stringprep.pyx')
 | 
			
		||||
 | 
			
		||||
VERSION          = __version__
 | 
			
		||||
DESCRIPTION      = 'SleekXMPP is an elegant Python library for XMPP (aka Jabber, Google Talk, etc).'
 | 
			
		||||
with codecs.open('README.rst', 'r', encoding='UTF-8') as readme:
 | 
			
		||||
    LONG_DESCRIPTION = ''.join(readme)
 | 
			
		||||
from run_tests import TestCommand
 | 
			
		||||
from slixmpp.version import __version__
 | 
			
		||||
 | 
			
		||||
CLASSIFIERS      = [ 'Intended Audience :: Developers',
 | 
			
		||||
                     'License :: OSI Approved :: MIT License',
 | 
			
		||||
                     'Programming Language :: Python',
 | 
			
		||||
                     'Programming Language :: Python :: 2.6',
 | 
			
		||||
                     'Programming Language :: Python :: 2.7',
 | 
			
		||||
                     'Programming Language :: Python :: 3.1',
 | 
			
		||||
                     'Programming Language :: Python :: 3.2',
 | 
			
		||||
                     'Topic :: Software Development :: Libraries :: Python Modules',
 | 
			
		||||
                   ]
 | 
			
		||||
VERSION = __version__
 | 
			
		||||
DESCRIPTION = ('Slixmpp is an elegant Python library for XMPP (aka Jabber, '
 | 
			
		||||
               'Google Talk, etc).')
 | 
			
		||||
with open('README.rst', encoding='utf8') as readme:
 | 
			
		||||
    LONG_DESCRIPTION = readme.read()
 | 
			
		||||
 | 
			
		||||
packages     = [ 'sleekxmpp',
 | 
			
		||||
                 'sleekxmpp/stanza',
 | 
			
		||||
                 'sleekxmpp/test',
 | 
			
		||||
                 'sleekxmpp/roster',
 | 
			
		||||
                 'sleekxmpp/util',
 | 
			
		||||
                 'sleekxmpp/util/sasl',
 | 
			
		||||
                 'sleekxmpp/xmlstream',
 | 
			
		||||
                 'sleekxmpp/xmlstream/matcher',
 | 
			
		||||
                 'sleekxmpp/xmlstream/handler',
 | 
			
		||||
                 'sleekxmpp/plugins',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0004',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0004/stanza',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0009',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0009/stanza',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0012',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0013',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0016',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0027',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0030',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0030/stanza',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0033',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0047',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0049',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0050',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0054',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0059',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0060',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0060/stanza',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0066',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0077',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0078',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0080',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0084',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0085',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0086',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0091',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0092',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0107',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0108',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0115',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0118',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0128',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0131',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0153',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0172',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0184',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0186',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0191',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0198',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0199',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0202',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0203',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0221',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0224',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0231',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0235',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0249',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0257',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0258',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0279',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0280',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0297',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0308',
 | 
			
		||||
                 'sleekxmpp/plugins/xep_0313',
 | 
			
		||||
                 'sleekxmpp/features',
 | 
			
		||||
                 'sleekxmpp/features/feature_mechanisms',
 | 
			
		||||
                 'sleekxmpp/features/feature_mechanisms/stanza',
 | 
			
		||||
                 'sleekxmpp/features/feature_starttls',
 | 
			
		||||
                 'sleekxmpp/features/feature_bind',
 | 
			
		||||
                 'sleekxmpp/features/feature_session',
 | 
			
		||||
                 'sleekxmpp/features/feature_rosterver',
 | 
			
		||||
                 'sleekxmpp/features/feature_preapproval',
 | 
			
		||||
                 'sleekxmpp/thirdparty',
 | 
			
		||||
                 ]
 | 
			
		||||
CLASSIFIERS = [
 | 
			
		||||
    'Intended Audience :: Developers',
 | 
			
		||||
    'License :: OSI Approved :: MIT License',
 | 
			
		||||
    'Programming Language :: Python',
 | 
			
		||||
    'Programming Language :: Python :: 3.4',
 | 
			
		||||
    'Topic :: Software Development :: Libraries :: Python Modules',
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
packages = [str(mod.parent) for mod in Path('slixmpp').rglob('__init__.py')]
 | 
			
		||||
 | 
			
		||||
setup(
 | 
			
		||||
    name             = "sleekxmpp",
 | 
			
		||||
    version          = VERSION,
 | 
			
		||||
    description      = DESCRIPTION,
 | 
			
		||||
    long_description = LONG_DESCRIPTION,
 | 
			
		||||
    author       = 'Nathanael Fritz',
 | 
			
		||||
    author_email = 'fritzy [at] netflint.net',
 | 
			
		||||
    url          = 'http://github.com/fritzy/SleekXMPP',
 | 
			
		||||
    license      = 'MIT',
 | 
			
		||||
    platforms    = [ 'any' ],
 | 
			
		||||
    packages     = packages,
 | 
			
		||||
    requires     = [ 'dnspython', 'pyasn1', 'pyasn1_modules' ],
 | 
			
		||||
    classifiers  = CLASSIFIERS,
 | 
			
		||||
    cmdclass     = {'test': TestCommand}
 | 
			
		||||
    name="slixmpp",
 | 
			
		||||
    version=VERSION,
 | 
			
		||||
    description=DESCRIPTION,
 | 
			
		||||
    long_description=LONG_DESCRIPTION,
 | 
			
		||||
    author='Florent Le Coz',
 | 
			
		||||
    author_email='louiz@louiz.org',
 | 
			
		||||
    url='https://dev.louiz.org/projects/slixmpp',
 | 
			
		||||
    license='MIT',
 | 
			
		||||
    platforms=['any'],
 | 
			
		||||
    packages=packages,
 | 
			
		||||
    ext_modules=ext_modules,
 | 
			
		||||
    requires=['aiodns', 'pyasn1', 'pyasn1_modules'],
 | 
			
		||||
    classifiers=CLASSIFIERS,
 | 
			
		||||
    cmdclass={'test': TestCommand}
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2010  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.basexmpp import BaseXMPP
 | 
			
		||||
from sleekxmpp.clientxmpp import ClientXMPP
 | 
			
		||||
from sleekxmpp.componentxmpp import ComponentXMPP
 | 
			
		||||
from sleekxmpp.stanza import Message, Presence, Iq
 | 
			
		||||
from sleekxmpp.jid import JID, InvalidJID
 | 
			
		||||
from sleekxmpp.xmlstream.handler import *
 | 
			
		||||
from sleekxmpp.xmlstream import XMLStream, RestartStream
 | 
			
		||||
from sleekxmpp.xmlstream.matcher import *
 | 
			
		||||
from sleekxmpp.xmlstream.stanzabase import StanzaBase, ET
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.version import __version__, __version_info__
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.features.feature_bind.bind import FeatureBind
 | 
			
		||||
from sleekxmpp.features.feature_bind.stanza import Bind
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(FeatureBind)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
feature_bind = FeatureBind
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.mechanisms import FeatureMechanisms
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza import Mechanisms
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza import Auth
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza import Success
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza import Failure
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(FeatureMechanisms)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
feature_mechanisms = FeatureMechanisms
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza.mechanisms import Mechanisms
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza.auth import Auth
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza.success import Success
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza.failure import Failure
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza.challenge import Challenge
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza.response import Response
 | 
			
		||||
from sleekxmpp.features.feature_mechanisms.stanza.abort import Abort
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2012  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.features.feature_preapproval.preapproval import FeaturePreApproval
 | 
			
		||||
from sleekxmpp.features.feature_preapproval.stanza import PreApproval
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(FeaturePreApproval)
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2012  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.features.feature_rosterver.rosterver import FeatureRosterVer
 | 
			
		||||
from sleekxmpp.features.feature_rosterver.stanza import RosterVer
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(FeatureRosterVer)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
feature_rosterver = FeatureRosterVer
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.features.feature_session.session import FeatureSession
 | 
			
		||||
from sleekxmpp.features.feature_session.stanza import Session
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(FeatureSession)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
feature_session = FeatureSession
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011  Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.features.feature_starttls.starttls import FeatureSTARTTLS
 | 
			
		||||
from sleekxmpp.features.feature_starttls.stanza import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(FeatureSTARTTLS)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
feature_starttls = FeatureSTARTTLS
 | 
			
		||||
							
								
								
									
										582
									
								
								sleekxmpp/jid.py
									
									
									
									
									
								
							
							
						
						
									
										582
									
								
								sleekxmpp/jid.py
									
									
									
									
									
								
							@@ -1,582 +0,0 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
"""
 | 
			
		||||
    sleekxmpp.jid
 | 
			
		||||
    ~~~~~~~~~~~~~~~~~~~~~~~
 | 
			
		||||
 | 
			
		||||
    This module allows for working with Jabber IDs (JIDs).
 | 
			
		||||
 | 
			
		||||
    Part of SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
 | 
			
		||||
    :copyright: (c) 2011 Nathanael C. Fritz
 | 
			
		||||
    :license: MIT, see LICENSE for more details
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from __future__ import unicode_literals
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
import socket
 | 
			
		||||
import stringprep
 | 
			
		||||
import threading
 | 
			
		||||
import encodings.idna
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.util import stringprep_profiles
 | 
			
		||||
from sleekxmpp.thirdparty import OrderedDict
 | 
			
		||||
 | 
			
		||||
#: These characters are not allowed to appear in a JID.
 | 
			
		||||
ILLEGAL_CHARS = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r' + \
 | 
			
		||||
                '\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19' + \
 | 
			
		||||
                '\x1a\x1b\x1c\x1d\x1e\x1f' + \
 | 
			
		||||
                ' !"#$%&\'()*+,./:;<=>?@[\\]^_`{|}~\x7f'
 | 
			
		||||
 | 
			
		||||
#: The basic regex pattern that a JID must match in order to determine
 | 
			
		||||
#: the local, domain, and resource parts. This regex does NOT do any
 | 
			
		||||
#: validation, which requires application of nodeprep, resourceprep, etc.
 | 
			
		||||
JID_PATTERN = re.compile(
 | 
			
		||||
    "^(?:([^\"&'/:<>@]{1,1023})@)?([^/@]{1,1023})(?:/(.{1,1023}))?$"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
#: The set of escape sequences for the characters not allowed by nodeprep.
 | 
			
		||||
JID_ESCAPE_SEQUENCES = set(['\\20', '\\22', '\\26', '\\27', '\\2f',
 | 
			
		||||
                            '\\3a', '\\3c', '\\3e', '\\40', '\\5c'])
 | 
			
		||||
 | 
			
		||||
#: A mapping of unallowed characters to their escape sequences. An escape
 | 
			
		||||
#: sequence for '\' is also included since it must also be escaped in
 | 
			
		||||
#: certain situations.
 | 
			
		||||
JID_ESCAPE_TRANSFORMATIONS = {' ': '\\20',
 | 
			
		||||
                              '"': '\\22',
 | 
			
		||||
                              '&': '\\26',
 | 
			
		||||
                              "'": '\\27',
 | 
			
		||||
                              '/': '\\2f',
 | 
			
		||||
                              ':': '\\3a',
 | 
			
		||||
                              '<': '\\3c',
 | 
			
		||||
                              '>': '\\3e',
 | 
			
		||||
                              '@': '\\40',
 | 
			
		||||
                              '\\': '\\5c'}
 | 
			
		||||
 | 
			
		||||
#: The reverse mapping of escape sequences to their original forms.
 | 
			
		||||
JID_UNESCAPE_TRANSFORMATIONS = {'\\20': ' ',
 | 
			
		||||
                                '\\22': '"',
 | 
			
		||||
                                '\\26': '&',
 | 
			
		||||
                                '\\27': "'",
 | 
			
		||||
                                '\\2f': '/',
 | 
			
		||||
                                '\\3a': ':',
 | 
			
		||||
                                '\\3c': '<',
 | 
			
		||||
                                '\\3e': '>',
 | 
			
		||||
                                '\\40': '@',
 | 
			
		||||
                                '\\5c': '\\'}
 | 
			
		||||
 | 
			
		||||
JID_CACHE = OrderedDict()
 | 
			
		||||
JID_CACHE_LOCK = threading.Lock()
 | 
			
		||||
JID_CACHE_MAX_SIZE = 1024
 | 
			
		||||
 | 
			
		||||
def _cache(key, parts, locked):
 | 
			
		||||
    JID_CACHE[key] = (parts, locked)
 | 
			
		||||
    if len(JID_CACHE) > JID_CACHE_MAX_SIZE:
 | 
			
		||||
        with JID_CACHE_LOCK:
 | 
			
		||||
            while len(JID_CACHE) > JID_CACHE_MAX_SIZE:
 | 
			
		||||
                found = None
 | 
			
		||||
                for key, item in JID_CACHE.iteritems():
 | 
			
		||||
                    if not item[1]: # if not locked
 | 
			
		||||
                        found = key
 | 
			
		||||
                        break
 | 
			
		||||
                if not found: # more than MAX_SIZE locked
 | 
			
		||||
                    # warn?
 | 
			
		||||
                    break
 | 
			
		||||
                del JID_CACHE[found]
 | 
			
		||||
 | 
			
		||||
# pylint: disable=c0103
 | 
			
		||||
#: The nodeprep profile of stringprep used to validate the local,
 | 
			
		||||
#: or username, portion of a JID.
 | 
			
		||||
nodeprep = stringprep_profiles.create(
 | 
			
		||||
    nfkc=True,
 | 
			
		||||
    bidi=True,
 | 
			
		||||
    mappings=[
 | 
			
		||||
        stringprep_profiles.b1_mapping,
 | 
			
		||||
        stringprep.map_table_b2],
 | 
			
		||||
    prohibited=[
 | 
			
		||||
        stringprep.in_table_c11,
 | 
			
		||||
        stringprep.in_table_c12,
 | 
			
		||||
        stringprep.in_table_c21,
 | 
			
		||||
        stringprep.in_table_c22,
 | 
			
		||||
        stringprep.in_table_c3,
 | 
			
		||||
        stringprep.in_table_c4,
 | 
			
		||||
        stringprep.in_table_c5,
 | 
			
		||||
        stringprep.in_table_c6,
 | 
			
		||||
        stringprep.in_table_c7,
 | 
			
		||||
        stringprep.in_table_c8,
 | 
			
		||||
        stringprep.in_table_c9,
 | 
			
		||||
        lambda c: c in ' \'"&/:<>@'],
 | 
			
		||||
    unassigned=[stringprep.in_table_a1])
 | 
			
		||||
 | 
			
		||||
# pylint: disable=c0103
 | 
			
		||||
#: The resourceprep profile of stringprep, which is used to validate
 | 
			
		||||
#: the resource portion of a JID.
 | 
			
		||||
resourceprep = stringprep_profiles.create(
 | 
			
		||||
    nfkc=True,
 | 
			
		||||
    bidi=True,
 | 
			
		||||
    mappings=[stringprep_profiles.b1_mapping],
 | 
			
		||||
    prohibited=[
 | 
			
		||||
        stringprep.in_table_c12,
 | 
			
		||||
        stringprep.in_table_c21,
 | 
			
		||||
        stringprep.in_table_c22,
 | 
			
		||||
        stringprep.in_table_c3,
 | 
			
		||||
        stringprep.in_table_c4,
 | 
			
		||||
        stringprep.in_table_c5,
 | 
			
		||||
        stringprep.in_table_c6,
 | 
			
		||||
        stringprep.in_table_c7,
 | 
			
		||||
        stringprep.in_table_c8,
 | 
			
		||||
        stringprep.in_table_c9],
 | 
			
		||||
    unassigned=[stringprep.in_table_a1])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _parse_jid(data):
 | 
			
		||||
    """
 | 
			
		||||
    Parse string data into the node, domain, and resource
 | 
			
		||||
    components of a JID, if possible.
 | 
			
		||||
 | 
			
		||||
    :param string data: A string that is potentially a JID.
 | 
			
		||||
 | 
			
		||||
    :raises InvalidJID:
 | 
			
		||||
 | 
			
		||||
    :returns: tuple of the validated local, domain, and resource strings
 | 
			
		||||
    """
 | 
			
		||||
    match = JID_PATTERN.match(data)
 | 
			
		||||
    if not match:
 | 
			
		||||
        raise InvalidJID('JID could not be parsed')
 | 
			
		||||
 | 
			
		||||
    (node, domain, resource) = match.groups()
 | 
			
		||||
 | 
			
		||||
    node = _validate_node(node)
 | 
			
		||||
    domain = _validate_domain(domain)
 | 
			
		||||
    resource = _validate_resource(resource)
 | 
			
		||||
 | 
			
		||||
    return node, domain, resource
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _validate_node(node):
 | 
			
		||||
    """Validate the local, or username, portion of a JID.
 | 
			
		||||
 | 
			
		||||
    :raises InvalidJID:
 | 
			
		||||
 | 
			
		||||
    :returns: The local portion of a JID, as validated by nodeprep.
 | 
			
		||||
    """
 | 
			
		||||
    try:
 | 
			
		||||
        if node is not None:
 | 
			
		||||
            node = nodeprep(node)
 | 
			
		||||
 | 
			
		||||
            if not node:
 | 
			
		||||
                raise InvalidJID('Localpart must not be 0 bytes')
 | 
			
		||||
            if len(node) > 1023:
 | 
			
		||||
                raise InvalidJID('Localpart must be less than 1024 bytes')
 | 
			
		||||
            return node
 | 
			
		||||
    except stringprep_profiles.StringPrepError:
 | 
			
		||||
        raise InvalidJID('Invalid local part')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _validate_domain(domain):
 | 
			
		||||
    """Validate the domain portion of a JID.
 | 
			
		||||
 | 
			
		||||
    IP literal addresses are left as-is, if valid. Domain names
 | 
			
		||||
    are stripped of any trailing label separators (`.`), and are
 | 
			
		||||
    checked with the nameprep profile of stringprep. If the given
 | 
			
		||||
    domain is actually a punyencoded version of a domain name, it
 | 
			
		||||
    is converted back into its original Unicode form. Domains must
 | 
			
		||||
    also not start or end with a dash (`-`).
 | 
			
		||||
 | 
			
		||||
    :raises InvalidJID:
 | 
			
		||||
 | 
			
		||||
    :returns: The validated domain name
 | 
			
		||||
    """
 | 
			
		||||
    ip_addr = False
 | 
			
		||||
 | 
			
		||||
    # First, check if this is an IPv4 address
 | 
			
		||||
    try:
 | 
			
		||||
        socket.inet_aton(domain)
 | 
			
		||||
        ip_addr = True
 | 
			
		||||
    except socket.error:
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    # Check if this is an IPv6 address
 | 
			
		||||
    if not ip_addr and hasattr(socket, 'inet_pton'):
 | 
			
		||||
        try:
 | 
			
		||||
            socket.inet_pton(socket.AF_INET6, domain.strip('[]'))
 | 
			
		||||
            domain = '[%s]' % domain.strip('[]')
 | 
			
		||||
            ip_addr = True
 | 
			
		||||
        except socket.error:
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    if not ip_addr:
 | 
			
		||||
        # This is a domain name, which must be checked further
 | 
			
		||||
 | 
			
		||||
        if domain and domain[-1] == '.':
 | 
			
		||||
            domain = domain[:-1]
 | 
			
		||||
 | 
			
		||||
        domain_parts = []
 | 
			
		||||
        for label in domain.split('.'):
 | 
			
		||||
            try:
 | 
			
		||||
                label = encodings.idna.nameprep(label)
 | 
			
		||||
                encodings.idna.ToASCII(label)
 | 
			
		||||
                pass_nameprep = True
 | 
			
		||||
            except UnicodeError:
 | 
			
		||||
                pass_nameprep = False
 | 
			
		||||
 | 
			
		||||
            if not pass_nameprep:
 | 
			
		||||
                raise InvalidJID('Could not encode domain as ASCII')
 | 
			
		||||
 | 
			
		||||
            if label.startswith('xn--'):
 | 
			
		||||
                label = encodings.idna.ToUnicode(label)
 | 
			
		||||
 | 
			
		||||
            for char in label:
 | 
			
		||||
                if char in ILLEGAL_CHARS:
 | 
			
		||||
                    raise InvalidJID('Domain contains illegar characters')
 | 
			
		||||
 | 
			
		||||
            if '-' in (label[0], label[-1]):
 | 
			
		||||
                raise InvalidJID('Domain started or ended with -')
 | 
			
		||||
 | 
			
		||||
            domain_parts.append(label)
 | 
			
		||||
        domain = '.'.join(domain_parts)
 | 
			
		||||
 | 
			
		||||
    if not domain:
 | 
			
		||||
        raise InvalidJID('Domain must not be 0 bytes')
 | 
			
		||||
    if len(domain) > 1023:
 | 
			
		||||
        raise InvalidJID('Domain must be less than 1024 bytes')
 | 
			
		||||
 | 
			
		||||
    return domain
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _validate_resource(resource):
 | 
			
		||||
    """Validate the resource portion of a JID.
 | 
			
		||||
 | 
			
		||||
    :raises InvalidJID:
 | 
			
		||||
 | 
			
		||||
    :returns: The local portion of a JID, as validated by resourceprep.
 | 
			
		||||
    """
 | 
			
		||||
    try:
 | 
			
		||||
        if resource is not None:
 | 
			
		||||
            resource = resourceprep(resource)
 | 
			
		||||
 | 
			
		||||
            if not resource:
 | 
			
		||||
                raise InvalidJID('Resource must not be 0 bytes')
 | 
			
		||||
            if len(resource) > 1023:
 | 
			
		||||
                raise InvalidJID('Resource must be less than 1024 bytes')
 | 
			
		||||
            return resource
 | 
			
		||||
    except stringprep_profiles.StringPrepError:
 | 
			
		||||
        raise InvalidJID('Invalid resource')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _escape_node(node):
 | 
			
		||||
    """Escape the local portion of a JID."""
 | 
			
		||||
    result = []
 | 
			
		||||
 | 
			
		||||
    for i, char in enumerate(node):
 | 
			
		||||
        if char == '\\':
 | 
			
		||||
            if ''.join((node[i:i+3])) in JID_ESCAPE_SEQUENCES:
 | 
			
		||||
                result.append('\\5c')
 | 
			
		||||
                continue
 | 
			
		||||
        result.append(char)
 | 
			
		||||
 | 
			
		||||
    for i, char in enumerate(result):
 | 
			
		||||
        if char != '\\':
 | 
			
		||||
            result[i] = JID_ESCAPE_TRANSFORMATIONS.get(char, char)
 | 
			
		||||
 | 
			
		||||
    escaped = ''.join(result)
 | 
			
		||||
 | 
			
		||||
    if escaped.startswith('\\20') or escaped.endswith('\\20'):
 | 
			
		||||
        raise InvalidJID('Escaped local part starts or ends with "\\20"')
 | 
			
		||||
 | 
			
		||||
    _validate_node(escaped)
 | 
			
		||||
 | 
			
		||||
    return escaped
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _unescape_node(node):
 | 
			
		||||
    """Unescape a local portion of a JID.
 | 
			
		||||
 | 
			
		||||
    .. note::
 | 
			
		||||
        The unescaped local portion is meant ONLY for presentation,
 | 
			
		||||
        and should not be used for other purposes.
 | 
			
		||||
    """
 | 
			
		||||
    unescaped = []
 | 
			
		||||
    seq = ''
 | 
			
		||||
    for i, char in enumerate(node):
 | 
			
		||||
        if char == '\\':
 | 
			
		||||
            seq = node[i:i+3]
 | 
			
		||||
            if seq not in JID_ESCAPE_SEQUENCES:
 | 
			
		||||
                seq = ''
 | 
			
		||||
        if seq:
 | 
			
		||||
            if len(seq) == 3:
 | 
			
		||||
                unescaped.append(JID_UNESCAPE_TRANSFORMATIONS.get(seq, char))
 | 
			
		||||
 | 
			
		||||
            # Pop character off the escape sequence, and ignore it
 | 
			
		||||
            seq = seq[1:]
 | 
			
		||||
        else:
 | 
			
		||||
            unescaped.append(char)
 | 
			
		||||
    unescaped = ''.join(unescaped)
 | 
			
		||||
 | 
			
		||||
    return unescaped
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _format_jid(local=None, domain=None, resource=None):
 | 
			
		||||
    """Format the given JID components into a full or bare JID.
 | 
			
		||||
 | 
			
		||||
    :param string local: Optional. The local portion of the JID.
 | 
			
		||||
    :param string domain: Required. The domain name portion of the JID.
 | 
			
		||||
    :param strin resource: Optional. The resource portion of the JID.
 | 
			
		||||
 | 
			
		||||
    :return: A full or bare JID string.
 | 
			
		||||
    """
 | 
			
		||||
    result = []
 | 
			
		||||
    if local:
 | 
			
		||||
        result.append(local)
 | 
			
		||||
        result.append('@')
 | 
			
		||||
    if domain:
 | 
			
		||||
        result.append(domain)
 | 
			
		||||
    if resource:
 | 
			
		||||
        result.append('/')
 | 
			
		||||
        result.append(resource)
 | 
			
		||||
    return ''.join(result)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InvalidJID(ValueError):
 | 
			
		||||
    """
 | 
			
		||||
    Raised when attempting to create a JID that does not pass validation.
 | 
			
		||||
 | 
			
		||||
    It can also be raised if modifying an existing JID in such a way as
 | 
			
		||||
    to make it invalid, such trying to remove the domain from an existing
 | 
			
		||||
    full JID while the local and resource portions still exist.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
# pylint: disable=R0903
 | 
			
		||||
class UnescapedJID(object):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    .. versionadded:: 1.1.10
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, local, domain, resource):
 | 
			
		||||
        self._jid = (local, domain, resource)
 | 
			
		||||
 | 
			
		||||
    # pylint: disable=R0911
 | 
			
		||||
    def __getattr__(self, name):
 | 
			
		||||
        """Retrieve the given JID component.
 | 
			
		||||
 | 
			
		||||
        :param name: one of: user, server, domain, resource,
 | 
			
		||||
                     full, or bare.
 | 
			
		||||
        """
 | 
			
		||||
        if name == 'resource':
 | 
			
		||||
            return self._jid[2] or ''
 | 
			
		||||
        elif name in ('user', 'username', 'local', 'node'):
 | 
			
		||||
            return self._jid[0] or ''
 | 
			
		||||
        elif name in ('server', 'domain', 'host'):
 | 
			
		||||
            return self._jid[1] or ''
 | 
			
		||||
        elif name in ('full', 'jid'):
 | 
			
		||||
            return _format_jid(*self._jid)
 | 
			
		||||
        elif name == 'bare':
 | 
			
		||||
            return _format_jid(self._jid[0], self._jid[1])
 | 
			
		||||
        elif name == '_jid':
 | 
			
		||||
            return getattr(super(JID, self), '_jid')
 | 
			
		||||
        else:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        """Use the full JID as the string value."""
 | 
			
		||||
        return _format_jid(*self._jid)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        """Use the full JID as the representation."""
 | 
			
		||||
        return self.__str__()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class JID(object):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    A representation of a Jabber ID, or JID.
 | 
			
		||||
 | 
			
		||||
    Each JID may have three components: a user, a domain, and an optional
 | 
			
		||||
    resource. For example: user@domain/resource
 | 
			
		||||
 | 
			
		||||
    When a resource is not used, the JID is called a bare JID.
 | 
			
		||||
    The JID is a full JID otherwise.
 | 
			
		||||
 | 
			
		||||
    **JID Properties:**
 | 
			
		||||
        :jid: Alias for ``full``.
 | 
			
		||||
        :full: The string value of the full JID.
 | 
			
		||||
        :bare: The string value of the bare JID.
 | 
			
		||||
        :user: The username portion of the JID.
 | 
			
		||||
        :username: Alias for ``user``.
 | 
			
		||||
        :local: Alias for ``user``.
 | 
			
		||||
        :node: Alias for ``user``.
 | 
			
		||||
        :domain: The domain name portion of the JID.
 | 
			
		||||
        :server: Alias for ``domain``.
 | 
			
		||||
        :host: Alias for ``domain``.
 | 
			
		||||
        :resource: The resource portion of the JID.
 | 
			
		||||
 | 
			
		||||
    :param string jid:
 | 
			
		||||
        A string of the form ``'[user@]domain[/resource]'``.
 | 
			
		||||
    :param string local:
 | 
			
		||||
        Optional. Specify the local, or username, portion
 | 
			
		||||
        of the JID. If provided, it will override the local
 | 
			
		||||
        value provided by the `jid` parameter. The given
 | 
			
		||||
        local value will also be escaped if necessary.
 | 
			
		||||
    :param string domain:
 | 
			
		||||
        Optional. Specify the domain of the JID. If
 | 
			
		||||
        provided, it will override the domain given by
 | 
			
		||||
        the `jid` parameter.
 | 
			
		||||
    :param string resource:
 | 
			
		||||
        Optional. Specify the resource value of the JID.
 | 
			
		||||
        If provided, it will override the domain given
 | 
			
		||||
        by the `jid` parameter.
 | 
			
		||||
 | 
			
		||||
    :raises InvalidJID:
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    # pylint: disable=W0212
 | 
			
		||||
    def __init__(self, jid=None, **kwargs):
 | 
			
		||||
        locked = kwargs.get('cache_lock', False)
 | 
			
		||||
        in_local = kwargs.get('local', None)
 | 
			
		||||
        in_domain = kwargs.get('domain', None)
 | 
			
		||||
        in_resource = kwargs.get('resource', None)
 | 
			
		||||
        parts = None
 | 
			
		||||
        if in_local or in_domain or in_resource:
 | 
			
		||||
            parts = (in_local, in_domain, in_resource)
 | 
			
		||||
 | 
			
		||||
        # only check cache if there is a jid string, or parts, not if there
 | 
			
		||||
        # are both
 | 
			
		||||
        self._jid = None
 | 
			
		||||
        key = None
 | 
			
		||||
        if (jid is not None) and (parts is None):
 | 
			
		||||
            if isinstance(jid, JID):
 | 
			
		||||
                # it's already good to go, and there are no additions
 | 
			
		||||
                self._jid = jid._jid
 | 
			
		||||
                return
 | 
			
		||||
            key = jid
 | 
			
		||||
            self._jid, locked = JID_CACHE.get(jid, (None, locked))
 | 
			
		||||
        elif jid is None and parts is not None:
 | 
			
		||||
            key = parts
 | 
			
		||||
            self._jid, locked = JID_CACHE.get(parts, (None, locked))
 | 
			
		||||
        if not self._jid:
 | 
			
		||||
            if not jid:
 | 
			
		||||
                parsed_jid = (None, None, None)
 | 
			
		||||
            elif not isinstance(jid, JID):
 | 
			
		||||
                parsed_jid = _parse_jid(jid)
 | 
			
		||||
            else:
 | 
			
		||||
                parsed_jid = jid._jid
 | 
			
		||||
 | 
			
		||||
            local, domain, resource = parsed_jid
 | 
			
		||||
 | 
			
		||||
            if 'local' in kwargs:
 | 
			
		||||
                local = _escape_node(in_local)
 | 
			
		||||
            if 'domain' in kwargs:
 | 
			
		||||
                domain = _validate_domain(in_domain)
 | 
			
		||||
            if 'resource' in kwargs:
 | 
			
		||||
                resource = _validate_resource(in_resource)
 | 
			
		||||
 | 
			
		||||
            self._jid = (local, domain, resource)
 | 
			
		||||
            if key:
 | 
			
		||||
                _cache(key, self._jid, locked)
 | 
			
		||||
 | 
			
		||||
    def unescape(self):
 | 
			
		||||
        """Return an unescaped JID object.
 | 
			
		||||
 | 
			
		||||
        Using an unescaped JID is preferred for displaying JIDs
 | 
			
		||||
        to humans, and they should NOT be used for any other
 | 
			
		||||
        purposes than for presentation.
 | 
			
		||||
 | 
			
		||||
        :return: :class:`UnescapedJID`
 | 
			
		||||
 | 
			
		||||
        .. versionadded:: 1.1.10
 | 
			
		||||
        """
 | 
			
		||||
        return UnescapedJID(_unescape_node(self._jid[0]),
 | 
			
		||||
                            self._jid[1],
 | 
			
		||||
                            self._jid[2])
 | 
			
		||||
 | 
			
		||||
    def regenerate(self):
 | 
			
		||||
        """No-op
 | 
			
		||||
 | 
			
		||||
        .. deprecated:: 1.1.10
 | 
			
		||||
        """
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def reset(self, data):
 | 
			
		||||
        """Start fresh from a new JID string.
 | 
			
		||||
 | 
			
		||||
        :param string data: A string of the form ``'[user@]domain[/resource]'``.
 | 
			
		||||
 | 
			
		||||
        .. deprecated:: 1.1.10
 | 
			
		||||
        """
 | 
			
		||||
        self._jid = JID(data)._jid
 | 
			
		||||
 | 
			
		||||
    # pylint: disable=R0911
 | 
			
		||||
    def __getattr__(self, name):
 | 
			
		||||
        """Retrieve the given JID component.
 | 
			
		||||
 | 
			
		||||
        :param name: one of: user, server, domain, resource,
 | 
			
		||||
                     full, or bare.
 | 
			
		||||
        """
 | 
			
		||||
        if name == 'resource':
 | 
			
		||||
            return self._jid[2] or ''
 | 
			
		||||
        elif name in ('user', 'username', 'local', 'node'):
 | 
			
		||||
            return self._jid[0] or ''
 | 
			
		||||
        elif name in ('server', 'domain', 'host'):
 | 
			
		||||
            return self._jid[1] or ''
 | 
			
		||||
        elif name in ('full', 'jid'):
 | 
			
		||||
            return _format_jid(*self._jid)
 | 
			
		||||
        elif name == 'bare':
 | 
			
		||||
            return _format_jid(self._jid[0], self._jid[1])
 | 
			
		||||
        elif name == '_jid':
 | 
			
		||||
            return getattr(super(JID, self), '_jid')
 | 
			
		||||
        else:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
    # pylint: disable=W0212
 | 
			
		||||
    def __setattr__(self, name, value):
 | 
			
		||||
        """Update the given JID component.
 | 
			
		||||
 | 
			
		||||
        :param name: one of: ``user``, ``username``, ``local``,
 | 
			
		||||
                             ``node``, ``server``, ``domain``, ``host``,
 | 
			
		||||
                             ``resource``, ``full``, ``jid``, or ``bare``.
 | 
			
		||||
        :param value: The new string value of the JID component.
 | 
			
		||||
        """
 | 
			
		||||
        if name == '_jid':
 | 
			
		||||
            super(JID, self).__setattr__('_jid', value)
 | 
			
		||||
        elif name == 'resource':
 | 
			
		||||
            self._jid = JID(self, resource=value)._jid
 | 
			
		||||
        elif name in ('user', 'username', 'local', 'node'):
 | 
			
		||||
            self._jid = JID(self, local=value)._jid
 | 
			
		||||
        elif name in ('server', 'domain', 'host'):
 | 
			
		||||
            self._jid = JID(self, domain=value)._jid
 | 
			
		||||
        elif name in ('full', 'jid'):
 | 
			
		||||
            self._jid = JID(value)._jid
 | 
			
		||||
        elif name == 'bare':
 | 
			
		||||
            parsed = JID(value)._jid
 | 
			
		||||
            self._jid = (parsed[0], parsed[1], self._jid[2])
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        """Use the full JID as the string value."""
 | 
			
		||||
        return _format_jid(*self._jid)
 | 
			
		||||
 | 
			
		||||
    def __repr__(self):
 | 
			
		||||
        """Use the full JID as the representation."""
 | 
			
		||||
        return self.__str__()
 | 
			
		||||
 | 
			
		||||
    # pylint: disable=W0212
 | 
			
		||||
    def __eq__(self, other):
 | 
			
		||||
        """Two JIDs are equal if they have the same full JID value."""
 | 
			
		||||
        if isinstance(other, UnescapedJID):
 | 
			
		||||
            return False
 | 
			
		||||
 | 
			
		||||
        other = JID(other)
 | 
			
		||||
        return self._jid == other._jid
 | 
			
		||||
 | 
			
		||||
    # pylint: disable=W0212
 | 
			
		||||
    def __ne__(self, other):
 | 
			
		||||
        """Two JIDs are considered unequal if they are not equal."""
 | 
			
		||||
        return not self == other
 | 
			
		||||
 | 
			
		||||
    def __hash__(self):
 | 
			
		||||
        """Hash a JID based on the string version of its full JID."""
 | 
			
		||||
        return hash(self.__str__())
 | 
			
		||||
 | 
			
		||||
    def __copy__(self):
 | 
			
		||||
        """Generate a duplicate JID."""
 | 
			
		||||
        return JID(self)
 | 
			
		||||
@@ -1,49 +0,0 @@
 | 
			
		||||
from . import base
 | 
			
		||||
import logging
 | 
			
		||||
from xml.etree import cElementTree as ET
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
log = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class jobs(base.base_plugin):
 | 
			
		||||
	def plugin_init(self):
 | 
			
		||||
		self.xep = 'pubsubjob'
 | 
			
		||||
		self.description = "Job distribution over Pubsub"
 | 
			
		||||
 | 
			
		||||
	def post_init(self):
 | 
			
		||||
		pass
 | 
			
		||||
		#TODO add event
 | 
			
		||||
 | 
			
		||||
	def createJobNode(self, host, jid, node, config=None):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	def createJob(self, host, node, jobid=None, payload=None):
 | 
			
		||||
		return self.xmpp.plugin['xep_0060'].setItem(host, node, ((jobid, payload),))
 | 
			
		||||
 | 
			
		||||
	def claimJob(self, host, node, jobid, ifrom=None):
 | 
			
		||||
		return self._setState(host, node, jobid, ET.Element('{http://andyet.net/protocol/pubsubjob}claimed'))
 | 
			
		||||
 | 
			
		||||
	def unclaimJob(self, host, node, jobid):
 | 
			
		||||
		return self._setState(host, node, jobid, ET.Element('{http://andyet.net/protocol/pubsubjob}unclaimed'))
 | 
			
		||||
 | 
			
		||||
	def finishJob(self, host, node, jobid, payload=None):
 | 
			
		||||
		finished = ET.Element('{http://andyet.net/protocol/pubsubjob}finished')
 | 
			
		||||
		if payload is not None:
 | 
			
		||||
			finished.append(payload)
 | 
			
		||||
		return self._setState(host, node, jobid, finished)
 | 
			
		||||
 | 
			
		||||
	def _setState(self, host, node, jobid, state, ifrom=None):
 | 
			
		||||
		iq = self.xmpp.Iq()
 | 
			
		||||
		iq['to'] = host
 | 
			
		||||
		if ifrom: iq['from'] = ifrom
 | 
			
		||||
		iq['type'] = 'set'
 | 
			
		||||
		iq['psstate']['node'] = node
 | 
			
		||||
		iq['psstate']['item'] = jobid
 | 
			
		||||
		iq['psstate']['payload'] = state
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is None or type(result) == bool or result['type'] != 'result':
 | 
			
		||||
			log.error("Unable to change %s:%s to %s", node, jobid, state)
 | 
			
		||||
			return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
@@ -1,421 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2010 Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
from . import base
 | 
			
		||||
import logging
 | 
			
		||||
from xml.etree import cElementTree as ET
 | 
			
		||||
import copy
 | 
			
		||||
import logging
 | 
			
		||||
#TODO support item groups and results
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
log = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class old_0004(base.base_plugin):
 | 
			
		||||
 | 
			
		||||
	def plugin_init(self):
 | 
			
		||||
		self.xep = '0004'
 | 
			
		||||
		self.description = '*Deprecated Data Forms'
 | 
			
		||||
		self.xmpp.add_handler("<message><x xmlns='jabber:x:data' /></message>", self.handler_message_xform, name='Old Message Form')
 | 
			
		||||
 | 
			
		||||
	def post_init(self):
 | 
			
		||||
		base.base_plugin.post_init(self)
 | 
			
		||||
		self.xmpp.plugin['xep_0030'].add_feature('jabber:x:data')
 | 
			
		||||
		log.warning("This implementation of XEP-0004 is deprecated.")
 | 
			
		||||
 | 
			
		||||
	def handler_message_xform(self, xml):
 | 
			
		||||
		object = self.handle_form(xml)
 | 
			
		||||
		self.xmpp.event("message_form", object)
 | 
			
		||||
 | 
			
		||||
	def handler_presence_xform(self, xml):
 | 
			
		||||
		object = self.handle_form(xml)
 | 
			
		||||
		self.xmpp.event("presence_form", object)
 | 
			
		||||
 | 
			
		||||
	def handle_form(self, xml):
 | 
			
		||||
		xmlform = xml.find('{jabber:x:data}x')
 | 
			
		||||
		object = self.buildForm(xmlform)
 | 
			
		||||
		self.xmpp.event("message_xform", object)
 | 
			
		||||
		return object
 | 
			
		||||
 | 
			
		||||
	def buildForm(self, xml):
 | 
			
		||||
		form = Form(ftype=xml.attrib['type'])
 | 
			
		||||
		form.fromXML(xml)
 | 
			
		||||
		return form
 | 
			
		||||
 | 
			
		||||
	def makeForm(self, ftype='form', title='', instructions=''):
 | 
			
		||||
		return Form(self.xmpp, ftype, title, instructions)
 | 
			
		||||
 | 
			
		||||
class FieldContainer(object):
 | 
			
		||||
	def __init__(self, stanza = 'form'):
 | 
			
		||||
		self.fields = []
 | 
			
		||||
		self.field = {}
 | 
			
		||||
		self.stanza = stanza
 | 
			
		||||
 | 
			
		||||
	def addField(self, var, ftype='text-single', label='', desc='', required=False, value=None):
 | 
			
		||||
		self.field[var] = FormField(var, ftype, label, desc, required, value)
 | 
			
		||||
		self.fields.append(self.field[var])
 | 
			
		||||
		return self.field[var]
 | 
			
		||||
 | 
			
		||||
	def buildField(self, xml):
 | 
			
		||||
		self.field[xml.get('var', '__unnamed__')] = FormField(xml.get('var', '__unnamed__'), xml.get('type', 'text-single'))
 | 
			
		||||
		self.fields.append(self.field[xml.get('var', '__unnamed__')])
 | 
			
		||||
		self.field[xml.get('var', '__unnamed__')].buildField(xml)
 | 
			
		||||
 | 
			
		||||
	def buildContainer(self, xml):
 | 
			
		||||
		self.stanza = xml.tag
 | 
			
		||||
		for field in xml.findall('{jabber:x:data}field'):
 | 
			
		||||
			self.buildField(field)
 | 
			
		||||
 | 
			
		||||
	def getXML(self, ftype):
 | 
			
		||||
		container = ET.Element(self.stanza)
 | 
			
		||||
		for field in self.fields:
 | 
			
		||||
			container.append(field.getXML(ftype))
 | 
			
		||||
		return container
 | 
			
		||||
 | 
			
		||||
class Form(FieldContainer):
 | 
			
		||||
	types = ('form', 'submit', 'cancel', 'result')
 | 
			
		||||
	def __init__(self, xmpp=None, ftype='form', title='', instructions=''):
 | 
			
		||||
		if not ftype in self.types:
 | 
			
		||||
			raise ValueError("Invalid Form Type")
 | 
			
		||||
		FieldContainer.__init__(self)
 | 
			
		||||
		self.xmpp = xmpp
 | 
			
		||||
		self.type = ftype
 | 
			
		||||
		self.title = title
 | 
			
		||||
		self.instructions = instructions
 | 
			
		||||
		self.reported = []
 | 
			
		||||
		self.items = []
 | 
			
		||||
 | 
			
		||||
	def merge(self, form2):
 | 
			
		||||
		form1 = Form(ftype=self.type)
 | 
			
		||||
		form1.fromXML(self.getXML(self.type))
 | 
			
		||||
		for field in form2.fields:
 | 
			
		||||
			if not field.var in form1.field:
 | 
			
		||||
				form1.addField(field.var, field.type, field.label, field.desc, field.required, field.value)
 | 
			
		||||
			else:
 | 
			
		||||
				form1.field[field.var].value = field.value
 | 
			
		||||
			for option, label in field.options:
 | 
			
		||||
				if (option, label) not in form1.field[field.var].options:
 | 
			
		||||
					form1.fields[field.var].addOption(option, label)
 | 
			
		||||
		return form1
 | 
			
		||||
 | 
			
		||||
	def copy(self):
 | 
			
		||||
		newform = Form(ftype=self.type)
 | 
			
		||||
		newform.fromXML(self.getXML(self.type))
 | 
			
		||||
		return newform
 | 
			
		||||
 | 
			
		||||
	def update(self, form):
 | 
			
		||||
		values = form.getValues()
 | 
			
		||||
		for var in values:
 | 
			
		||||
			if var in self.fields:
 | 
			
		||||
				self.fields[var].setValue(self.fields[var])
 | 
			
		||||
 | 
			
		||||
	def getValues(self):
 | 
			
		||||
		result = {}
 | 
			
		||||
		for field in self.fields:
 | 
			
		||||
			value = field.value
 | 
			
		||||
			if len(value) == 1:
 | 
			
		||||
				value = value[0]
 | 
			
		||||
			result[field.var] = value
 | 
			
		||||
		return result
 | 
			
		||||
 | 
			
		||||
	def setValues(self, values={}):
 | 
			
		||||
		for field in values:
 | 
			
		||||
			if field in self.field:
 | 
			
		||||
				if isinstance(values[field], list) or isinstance(values[field], tuple):
 | 
			
		||||
					for value in values[field]:
 | 
			
		||||
						self.field[field].setValue(value)
 | 
			
		||||
				else:
 | 
			
		||||
					self.field[field].setValue(values[field])
 | 
			
		||||
 | 
			
		||||
	def fromXML(self, xml):
 | 
			
		||||
		self.buildForm(xml)
 | 
			
		||||
 | 
			
		||||
	def addItem(self):
 | 
			
		||||
		newitem = FieldContainer('item')
 | 
			
		||||
		self.items.append(newitem)
 | 
			
		||||
		return newitem
 | 
			
		||||
 | 
			
		||||
	def buildItem(self, xml):
 | 
			
		||||
		newitem = self.addItem()
 | 
			
		||||
		newitem.buildContainer(xml)
 | 
			
		||||
 | 
			
		||||
	def addReported(self):
 | 
			
		||||
		reported = FieldContainer('reported')
 | 
			
		||||
		self.reported.append(reported)
 | 
			
		||||
		return reported
 | 
			
		||||
 | 
			
		||||
	def buildReported(self, xml):
 | 
			
		||||
		reported = self.addReported()
 | 
			
		||||
		reported.buildContainer(xml)
 | 
			
		||||
 | 
			
		||||
	def setTitle(self, title):
 | 
			
		||||
		self.title = title
 | 
			
		||||
 | 
			
		||||
	def setInstructions(self, instructions):
 | 
			
		||||
		self.instructions = instructions
 | 
			
		||||
 | 
			
		||||
	def setType(self, ftype):
 | 
			
		||||
		self.type = ftype
 | 
			
		||||
 | 
			
		||||
	def getXMLMessage(self, to):
 | 
			
		||||
		msg = self.xmpp.makeMessage(to)
 | 
			
		||||
		msg.append(self.getXML())
 | 
			
		||||
		return msg
 | 
			
		||||
 | 
			
		||||
	def buildForm(self, xml):
 | 
			
		||||
		self.type = xml.get('type', 'form')
 | 
			
		||||
		if xml.find('{jabber:x:data}title') is not None:
 | 
			
		||||
			self.setTitle(xml.find('{jabber:x:data}title').text)
 | 
			
		||||
		if xml.find('{jabber:x:data}instructions') is not None:
 | 
			
		||||
			self.setInstructions(xml.find('{jabber:x:data}instructions').text)
 | 
			
		||||
		for field in xml.findall('{jabber:x:data}field'):
 | 
			
		||||
			self.buildField(field)
 | 
			
		||||
		for reported in xml.findall('{jabber:x:data}reported'):
 | 
			
		||||
			self.buildReported(reported)
 | 
			
		||||
		for item in xml.findall('{jabber:x:data}item'):
 | 
			
		||||
			self.buildItem(item)
 | 
			
		||||
 | 
			
		||||
	#def getXML(self, tostring = False):
 | 
			
		||||
	def getXML(self, ftype=None):
 | 
			
		||||
		if ftype:
 | 
			
		||||
			self.type = ftype
 | 
			
		||||
		form = ET.Element('{jabber:x:data}x')
 | 
			
		||||
		form.attrib['type'] = self.type
 | 
			
		||||
		if self.title and self.type in ('form', 'result'):
 | 
			
		||||
			title = ET.Element('{jabber:x:data}title')
 | 
			
		||||
			title.text = self.title
 | 
			
		||||
			form.append(title)
 | 
			
		||||
		if self.instructions and self.type == 'form':
 | 
			
		||||
			instructions = ET.Element('{jabber:x:data}instructions')
 | 
			
		||||
			instructions.text = self.instructions
 | 
			
		||||
			form.append(instructions)
 | 
			
		||||
		for field in self.fields:
 | 
			
		||||
			form.append(field.getXML(self.type))
 | 
			
		||||
		for reported in self.reported:
 | 
			
		||||
			form.append(reported.getXML('{jabber:x:data}reported'))
 | 
			
		||||
		for item in self.items:
 | 
			
		||||
			form.append(item.getXML(self.type))
 | 
			
		||||
		#if tostring:
 | 
			
		||||
		#	form = self.xmpp.tostring(form)
 | 
			
		||||
		return form
 | 
			
		||||
 | 
			
		||||
	def getXHTML(self):
 | 
			
		||||
		form = ET.Element('{http://www.w3.org/1999/xhtml}form')
 | 
			
		||||
		if self.title:
 | 
			
		||||
			title = ET.Element('h2')
 | 
			
		||||
			title.text = self.title
 | 
			
		||||
			form.append(title)
 | 
			
		||||
		if self.instructions:
 | 
			
		||||
			instructions = ET.Element('p')
 | 
			
		||||
			instructions.text = self.instructions
 | 
			
		||||
			form.append(instructions)
 | 
			
		||||
		for field in self.fields:
 | 
			
		||||
			form.append(field.getXHTML())
 | 
			
		||||
		for field in self.reported:
 | 
			
		||||
			form.append(field.getXHTML())
 | 
			
		||||
		for field in self.items:
 | 
			
		||||
			form.append(field.getXHTML())
 | 
			
		||||
		return form
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	def makeSubmit(self):
 | 
			
		||||
		self.setType('submit')
 | 
			
		||||
 | 
			
		||||
class FormField(object):
 | 
			
		||||
	types = ('boolean', 'fixed', 'hidden', 'jid-multi', 'jid-single', 'list-multi', 'list-single', 'text-multi', 'text-private', 'text-single')
 | 
			
		||||
	listtypes = ('jid-multi', 'jid-single', 'list-multi', 'list-single')
 | 
			
		||||
	lbtypes = ('fixed', 'text-multi')
 | 
			
		||||
	def __init__(self, var, ftype='text-single', label='', desc='', required=False, value=None):
 | 
			
		||||
		if not ftype in self.types:
 | 
			
		||||
			raise ValueError("Invalid Field Type")
 | 
			
		||||
		self.type = ftype
 | 
			
		||||
		self.var = var
 | 
			
		||||
		self.label = label
 | 
			
		||||
		self.desc = desc
 | 
			
		||||
		self.options = []
 | 
			
		||||
		self.required = False
 | 
			
		||||
		self.value = []
 | 
			
		||||
		if self.type in self.listtypes:
 | 
			
		||||
			self.islist = True
 | 
			
		||||
		else:
 | 
			
		||||
			self.islist = False
 | 
			
		||||
		if self.type in self.lbtypes:
 | 
			
		||||
			self.islinebreak = True
 | 
			
		||||
		else:
 | 
			
		||||
			self.islinebreak = False
 | 
			
		||||
		if value:
 | 
			
		||||
			self.setValue(value)
 | 
			
		||||
 | 
			
		||||
	def addOption(self, value, label):
 | 
			
		||||
		if self.islist:
 | 
			
		||||
			self.options.append((value, label))
 | 
			
		||||
		else:
 | 
			
		||||
			raise ValueError("Cannot add options to non-list type field.")
 | 
			
		||||
 | 
			
		||||
	def setTrue(self):
 | 
			
		||||
		if self.type == 'boolean':
 | 
			
		||||
			self.value = [True]
 | 
			
		||||
 | 
			
		||||
	def setFalse(self):
 | 
			
		||||
		if self.type == 'boolean':
 | 
			
		||||
			self.value = [False]
 | 
			
		||||
 | 
			
		||||
	def require(self):
 | 
			
		||||
		self.required = True
 | 
			
		||||
 | 
			
		||||
	def setDescription(self, desc):
 | 
			
		||||
		self.desc = desc
 | 
			
		||||
 | 
			
		||||
	def setValue(self, value):
 | 
			
		||||
		if self.type == 'boolean':
 | 
			
		||||
			if value in ('1', 1, True, 'true', 'True', 'yes'):
 | 
			
		||||
				value = True
 | 
			
		||||
			else:
 | 
			
		||||
				value = False
 | 
			
		||||
		if self.islinebreak and value is not None:
 | 
			
		||||
			self.value += value.split('\n')
 | 
			
		||||
		else:
 | 
			
		||||
			if len(self.value) and (not self.islist or self.type == 'list-single'):
 | 
			
		||||
				self.value = [value]
 | 
			
		||||
			else:
 | 
			
		||||
				self.value.append(value)
 | 
			
		||||
 | 
			
		||||
	def delValue(self, value):
 | 
			
		||||
		if type(self.value) == type([]):
 | 
			
		||||
			try:
 | 
			
		||||
				idx = self.value.index(value)
 | 
			
		||||
				if idx != -1:
 | 
			
		||||
					self.value.pop(idx)
 | 
			
		||||
			except ValueError:
 | 
			
		||||
				pass
 | 
			
		||||
		else:
 | 
			
		||||
			self.value = ''
 | 
			
		||||
 | 
			
		||||
	def setAnswer(self, value):
 | 
			
		||||
		self.setValue(value)
 | 
			
		||||
 | 
			
		||||
	def buildField(self, xml):
 | 
			
		||||
		self.type = xml.get('type', 'text-single')
 | 
			
		||||
		self.label = xml.get('label', '')
 | 
			
		||||
		for option in xml.findall('{jabber:x:data}option'):
 | 
			
		||||
			self.addOption(option.find('{jabber:x:data}value').text, option.get('label', ''))
 | 
			
		||||
		for value in xml.findall('{jabber:x:data}value'):
 | 
			
		||||
			self.setValue(value.text)
 | 
			
		||||
		if xml.find('{jabber:x:data}required') is not None:
 | 
			
		||||
			self.require()
 | 
			
		||||
		if xml.find('{jabber:x:data}desc') is not None:
 | 
			
		||||
			self.setDescription(xml.find('{jabber:x:data}desc').text)
 | 
			
		||||
 | 
			
		||||
	def getXML(self, ftype):
 | 
			
		||||
		field = ET.Element('{jabber:x:data}field')
 | 
			
		||||
		if ftype != 'result':
 | 
			
		||||
			field.attrib['type'] = self.type
 | 
			
		||||
		if self.type != 'fixed':
 | 
			
		||||
			if self.var:
 | 
			
		||||
				field.attrib['var'] = self.var
 | 
			
		||||
			if self.label:
 | 
			
		||||
				field.attrib['label'] = self.label
 | 
			
		||||
		if ftype == 'form':
 | 
			
		||||
			for option in self.options:
 | 
			
		||||
				optionxml = ET.Element('{jabber:x:data}option')
 | 
			
		||||
				optionxml.attrib['label'] = option[1]
 | 
			
		||||
				optionval = ET.Element('{jabber:x:data}value')
 | 
			
		||||
				optionval.text = option[0]
 | 
			
		||||
				optionxml.append(optionval)
 | 
			
		||||
				field.append(optionxml)
 | 
			
		||||
			if self.required:
 | 
			
		||||
				required = ET.Element('{jabber:x:data}required')
 | 
			
		||||
				field.append(required)
 | 
			
		||||
			if self.desc:
 | 
			
		||||
				desc = ET.Element('{jabber:x:data}desc')
 | 
			
		||||
				desc.text = self.desc
 | 
			
		||||
				field.append(desc)
 | 
			
		||||
		for value in self.value:
 | 
			
		||||
			valuexml = ET.Element('{jabber:x:data}value')
 | 
			
		||||
			if value is True or value is False:
 | 
			
		||||
				if value:
 | 
			
		||||
					valuexml.text = '1'
 | 
			
		||||
				else:
 | 
			
		||||
					valuexml.text = '0'
 | 
			
		||||
			else:
 | 
			
		||||
				valuexml.text = value
 | 
			
		||||
			field.append(valuexml)
 | 
			
		||||
		return field
 | 
			
		||||
 | 
			
		||||
	def getXHTML(self):
 | 
			
		||||
		field = ET.Element('div', {'class': 'xmpp-xforms-%s' % self.type})
 | 
			
		||||
		if self.label:
 | 
			
		||||
			label = ET.Element('p')
 | 
			
		||||
			label.text = "%s: " % self.label
 | 
			
		||||
		else:
 | 
			
		||||
			label = ET.Element('p')
 | 
			
		||||
			label.text = "%s: " % self.var
 | 
			
		||||
		field.append(label)
 | 
			
		||||
		if self.type == 'boolean':
 | 
			
		||||
			formf = ET.Element('input', {'type': 'checkbox', 'name': self.var})
 | 
			
		||||
			if len(self.value) and self.value[0] in (True, 'true', '1'):
 | 
			
		||||
				formf.attrib['checked'] = 'checked'
 | 
			
		||||
		elif self.type == 'fixed':
 | 
			
		||||
			formf = ET.Element('p')
 | 
			
		||||
			try:
 | 
			
		||||
				formf.text = ', '.join(self.value)
 | 
			
		||||
			except:
 | 
			
		||||
				pass
 | 
			
		||||
			field.append(formf)
 | 
			
		||||
			formf = ET.Element('input', {'type': 'hidden', 'name': self.var})
 | 
			
		||||
			try:
 | 
			
		||||
				formf.text = ', '.join(self.value)
 | 
			
		||||
			except:
 | 
			
		||||
				pass
 | 
			
		||||
		elif self.type == 'hidden':
 | 
			
		||||
			formf = ET.Element('input', {'type': 'hidden', 'name': self.var})
 | 
			
		||||
			try:
 | 
			
		||||
				formf.text = ', '.join(self.value)
 | 
			
		||||
			except:
 | 
			
		||||
				pass
 | 
			
		||||
		elif self.type in ('jid-multi', 'list-multi'):
 | 
			
		||||
			formf = ET.Element('select', {'name': self.var})
 | 
			
		||||
			for option in self.options:
 | 
			
		||||
				optf = ET.Element('option', {'value': option[0], 'multiple': 'multiple'})
 | 
			
		||||
				optf.text = option[1]
 | 
			
		||||
				if option[1] in self.value:
 | 
			
		||||
					optf.attrib['selected'] = 'selected'
 | 
			
		||||
				formf.append(option)
 | 
			
		||||
		elif self.type in ('jid-single', 'text-single'):
 | 
			
		||||
			formf = ET.Element('input', {'type': 'text', 'name': self.var})
 | 
			
		||||
			try:
 | 
			
		||||
				formf.attrib['value'] = ', '.join(self.value)
 | 
			
		||||
			except:
 | 
			
		||||
				pass
 | 
			
		||||
		elif self.type == 'list-single':
 | 
			
		||||
			formf = ET.Element('select', {'name': self.var})
 | 
			
		||||
			for option in self.options:
 | 
			
		||||
				optf = ET.Element('option', {'value': option[0]})
 | 
			
		||||
				optf.text = option[1]
 | 
			
		||||
				if not optf.text:
 | 
			
		||||
					optf.text = option[0]
 | 
			
		||||
				if option[1] in self.value:
 | 
			
		||||
					optf.attrib['selected'] = 'selected'
 | 
			
		||||
				formf.append(optf)
 | 
			
		||||
		elif self.type == 'text-multi':
 | 
			
		||||
			formf = ET.Element('textarea', {'name': self.var})
 | 
			
		||||
			try:
 | 
			
		||||
				formf.text = ', '.join(self.value)
 | 
			
		||||
			except:
 | 
			
		||||
				pass
 | 
			
		||||
			if not formf.text:
 | 
			
		||||
				formf.text = ' '
 | 
			
		||||
		elif self.type == 'text-private':
 | 
			
		||||
			formf = ET.Element('input', {'type': 'password', 'name': self.var})
 | 
			
		||||
			try:
 | 
			
		||||
				formf.attrib['value'] = ', '.join(self.value)
 | 
			
		||||
			except:
 | 
			
		||||
				pass
 | 
			
		||||
		label.append(formf)
 | 
			
		||||
		return field
 | 
			
		||||
 | 
			
		||||
@@ -1,277 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
XEP-0009 XMPP Remote Procedure Calls
 | 
			
		||||
"""
 | 
			
		||||
from __future__ import with_statement
 | 
			
		||||
from . import base
 | 
			
		||||
import logging
 | 
			
		||||
from xml.etree import cElementTree as ET
 | 
			
		||||
import copy
 | 
			
		||||
import time
 | 
			
		||||
import base64
 | 
			
		||||
 | 
			
		||||
def py2xml(*args):
 | 
			
		||||
	params = ET.Element("params")
 | 
			
		||||
	for x in args:
 | 
			
		||||
		param = ET.Element("param")
 | 
			
		||||
		param.append(_py2xml(x))
 | 
			
		||||
		params.append(param) #<params><param>...
 | 
			
		||||
	return params
 | 
			
		||||
 | 
			
		||||
def _py2xml(*args):
 | 
			
		||||
	for x in args:
 | 
			
		||||
		val = ET.Element("value")
 | 
			
		||||
		if type(x) is int:
 | 
			
		||||
			i4 = ET.Element("i4")
 | 
			
		||||
			i4.text = str(x)
 | 
			
		||||
			val.append(i4)
 | 
			
		||||
		if type(x) is bool:
 | 
			
		||||
			boolean = ET.Element("boolean")
 | 
			
		||||
			boolean.text = str(int(x))
 | 
			
		||||
			val.append(boolean)
 | 
			
		||||
		elif type(x) is str:
 | 
			
		||||
			string = ET.Element("string")
 | 
			
		||||
			string.text = x
 | 
			
		||||
			val.append(string)
 | 
			
		||||
		elif type(x) is float:
 | 
			
		||||
			double = ET.Element("double")
 | 
			
		||||
			double.text = str(x)
 | 
			
		||||
			val.append(double)
 | 
			
		||||
		elif type(x) is rpcbase64:
 | 
			
		||||
			b64 = ET.Element("Base64")
 | 
			
		||||
			b64.text = x.encoded()
 | 
			
		||||
			val.append(b64)
 | 
			
		||||
		elif type(x) is rpctime:
 | 
			
		||||
			iso = ET.Element("dateTime.iso8601")
 | 
			
		||||
			iso.text = str(x)
 | 
			
		||||
			val.append(iso)
 | 
			
		||||
		elif type(x) is list:
 | 
			
		||||
			array = ET.Element("array")
 | 
			
		||||
			data = ET.Element("data")
 | 
			
		||||
			for y in x:
 | 
			
		||||
				data.append(_py2xml(y))
 | 
			
		||||
			array.append(data)
 | 
			
		||||
			val.append(array)
 | 
			
		||||
		elif type(x) is dict:
 | 
			
		||||
			struct = ET.Element("struct")
 | 
			
		||||
			for y in x.keys():
 | 
			
		||||
				member = ET.Element("member")
 | 
			
		||||
				name = ET.Element("name")
 | 
			
		||||
				name.text = y
 | 
			
		||||
				member.append(name)
 | 
			
		||||
				member.append(_py2xml(x[y]))
 | 
			
		||||
				struct.append(member)
 | 
			
		||||
			val.append(struct)
 | 
			
		||||
		return val
 | 
			
		||||
 | 
			
		||||
def xml2py(params):
 | 
			
		||||
	vals = []
 | 
			
		||||
	for param in params.findall('param'):
 | 
			
		||||
		vals.append(_xml2py(param.find('value')))
 | 
			
		||||
	return vals
 | 
			
		||||
 | 
			
		||||
def _xml2py(value):
 | 
			
		||||
	if value.find('i4') is not None:
 | 
			
		||||
		return int(value.find('i4').text)
 | 
			
		||||
	if value.find('int') is not None:
 | 
			
		||||
		return int(value.find('int').text)
 | 
			
		||||
	if value.find('boolean') is not None:
 | 
			
		||||
		return bool(value.find('boolean').text)
 | 
			
		||||
	if value.find('string') is not None:
 | 
			
		||||
		return value.find('string').text
 | 
			
		||||
	if value.find('double') is not None:
 | 
			
		||||
		return float(value.find('double').text)
 | 
			
		||||
	if value.find('Base64') is not None:
 | 
			
		||||
		return rpcbase64(value.find('Base64').text)
 | 
			
		||||
	if value.find('dateTime.iso8601') is not None:
 | 
			
		||||
		return rpctime(value.find('dateTime.iso8601'))
 | 
			
		||||
	if value.find('struct') is not None:
 | 
			
		||||
		struct = {}
 | 
			
		||||
		for member in value.find('struct').findall('member'):
 | 
			
		||||
			struct[member.find('name').text] = _xml2py(member.find('value'))
 | 
			
		||||
		return struct
 | 
			
		||||
	if value.find('array') is not None:
 | 
			
		||||
		array = []
 | 
			
		||||
		for val in value.find('array').find('data').findall('value'):
 | 
			
		||||
			array.append(_xml2py(val))
 | 
			
		||||
		return array
 | 
			
		||||
	raise ValueError()
 | 
			
		||||
 | 
			
		||||
class rpcbase64(object):
 | 
			
		||||
	def __init__(self, data):
 | 
			
		||||
		#base 64 encoded string
 | 
			
		||||
		self.data = data
 | 
			
		||||
 | 
			
		||||
	def decode(self):
 | 
			
		||||
		return base64.decodestring(data)
 | 
			
		||||
 | 
			
		||||
	def __str__(self):
 | 
			
		||||
		return self.decode()
 | 
			
		||||
 | 
			
		||||
	def encoded(self):
 | 
			
		||||
		return self.data
 | 
			
		||||
 | 
			
		||||
class rpctime(object):
 | 
			
		||||
	def __init__(self,data=None):
 | 
			
		||||
		#assume string data is in iso format YYYYMMDDTHH:MM:SS
 | 
			
		||||
		if type(data) is str:
 | 
			
		||||
			self.timestamp = time.strptime(data,"%Y%m%dT%H:%M:%S")
 | 
			
		||||
		elif type(data) is time.struct_time:
 | 
			
		||||
			self.timestamp = data
 | 
			
		||||
		elif data is None:
 | 
			
		||||
			self.timestamp = time.gmtime()
 | 
			
		||||
		else:
 | 
			
		||||
			raise ValueError()
 | 
			
		||||
 | 
			
		||||
	def iso8601(self):
 | 
			
		||||
		#return a iso8601 string
 | 
			
		||||
		return time.strftime("%Y%m%dT%H:%M:%S",self.timestamp)
 | 
			
		||||
 | 
			
		||||
	def __str__(self):
 | 
			
		||||
		return self.iso8601()
 | 
			
		||||
 | 
			
		||||
class JabberRPCEntry(object):
 | 
			
		||||
	def __init__(self,call):
 | 
			
		||||
		self.call = call
 | 
			
		||||
		self.result = None
 | 
			
		||||
		self.error = None
 | 
			
		||||
		self.allow = {} #{'<jid>':['<resource1>',...],...}
 | 
			
		||||
		self.deny = {}
 | 
			
		||||
 | 
			
		||||
	def check_acl(self, jid, resource):
 | 
			
		||||
		#Check for deny
 | 
			
		||||
		if jid in self.deny.keys():
 | 
			
		||||
			if self.deny[jid] == None or resource in self.deny[jid]:
 | 
			
		||||
				return False
 | 
			
		||||
		#Check for allow
 | 
			
		||||
		if allow == None:
 | 
			
		||||
			return True
 | 
			
		||||
		if jid in self.allow.keys():
 | 
			
		||||
			if self.allow[jid] == None or resource in self.allow[jid]:
 | 
			
		||||
				return True
 | 
			
		||||
		return False
 | 
			
		||||
 | 
			
		||||
	def acl_allow(self, jid, resource):
 | 
			
		||||
		if jid == None:
 | 
			
		||||
			self.allow = None
 | 
			
		||||
		elif resource == None:
 | 
			
		||||
			self.allow[jid] = None
 | 
			
		||||
		elif jid in self.allow.keys():
 | 
			
		||||
			self.allow[jid].append(resource)
 | 
			
		||||
		else:
 | 
			
		||||
			self.allow[jid] = [resource]
 | 
			
		||||
		
 | 
			
		||||
	def acl_deny(self, jid, resource):
 | 
			
		||||
		if jid == None:
 | 
			
		||||
			self.deny = None
 | 
			
		||||
		elif resource == None:
 | 
			
		||||
			self.deny[jid] = None
 | 
			
		||||
		elif jid in self.deny.keys():
 | 
			
		||||
			self.deny[jid].append(resource)
 | 
			
		||||
		else:
 | 
			
		||||
			self.deny[jid] = [resource]
 | 
			
		||||
 | 
			
		||||
	def call_method(self, args):
 | 
			
		||||
		ret = self.call(*args)
 | 
			
		||||
 | 
			
		||||
class xep_0009(base.base_plugin):
 | 
			
		||||
 | 
			
		||||
	def plugin_init(self):
 | 
			
		||||
		self.xep = '0009'
 | 
			
		||||
		self.description = 'Jabber-RPC'
 | 
			
		||||
		self.xmpp.add_handler("<iq type='set'><query xmlns='jabber:iq:rpc' /></iq>", 
 | 
			
		||||
                                      self._callMethod, name='Jabber RPC Call')
 | 
			
		||||
		self.xmpp.add_handler("<iq type='result'><query xmlns='jabber:iq:rpc' /></iq>", 
 | 
			
		||||
                                      self._callResult, name='Jabber RPC Result')
 | 
			
		||||
		self.xmpp.add_handler("<iq type='error'><query xmlns='jabber:iq:rpc' /></iq>", 
 | 
			
		||||
                                      self._callError, name='Jabber RPC Error')
 | 
			
		||||
		self.entries = {}
 | 
			
		||||
		self.activeCalls = []
 | 
			
		||||
 | 
			
		||||
	def post_init(self):
 | 
			
		||||
		base.base_plugin.post_init(self)
 | 
			
		||||
		self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:rpc')
 | 
			
		||||
		self.xmpp.plugin['xep_0030'].add_identity('automatition','rpc')
 | 
			
		||||
 | 
			
		||||
	def register_call(self, method, name=None):
 | 
			
		||||
		#@returns an string that can be used in acl commands.
 | 
			
		||||
		with self.lock:
 | 
			
		||||
			if name is None:
 | 
			
		||||
				self.entries[method.__name__] = JabberRPCEntry(method)
 | 
			
		||||
				return method.__name__
 | 
			
		||||
			else:
 | 
			
		||||
				self.entries[name] = JabberRPCEntry(method)
 | 
			
		||||
				return name
 | 
			
		||||
 | 
			
		||||
	def acl_allow(self, entry, jid=None, resource=None):
 | 
			
		||||
		#allow the method entry to be called by the given jid and resource.
 | 
			
		||||
		#if jid is None it will allow any jid/resource.
 | 
			
		||||
		#if resource is None it will allow any resource belonging to the jid.
 | 
			
		||||
		with self.lock:
 | 
			
		||||
			if self.entries[entry]:
 | 
			
		||||
				self.entries[entry].acl_allow(jid,resource)
 | 
			
		||||
			else:
 | 
			
		||||
				raise ValueError()
 | 
			
		||||
	
 | 
			
		||||
	def acl_deny(self, entry, jid=None, resource=None):
 | 
			
		||||
		#Note: by default all requests are denied unless allowed with acl_allow.
 | 
			
		||||
		#If you deny an entry it will not be allowed regardless of acl_allow
 | 
			
		||||
		with self.lock:
 | 
			
		||||
			if self.entries[entry]:
 | 
			
		||||
				self.entries[entry].acl_deny(jid,resource)
 | 
			
		||||
			else:
 | 
			
		||||
				raise ValueError()
 | 
			
		||||
	
 | 
			
		||||
	def unregister_call(self, entry):
 | 
			
		||||
		#removes the registered call
 | 
			
		||||
		with self.lock:
 | 
			
		||||
			if self.entries[entry]:
 | 
			
		||||
				del self.entries[entry]
 | 
			
		||||
			else:
 | 
			
		||||
				raise ValueError()
 | 
			
		||||
 | 
			
		||||
	def makeMethodCallQuery(self,pmethod,params):
 | 
			
		||||
		query = self.xmpp.makeIqQuery(iq,"jabber:iq:rpc")
 | 
			
		||||
		methodCall = ET.Element('methodCall')
 | 
			
		||||
		methodName = ET.Element('methodName')
 | 
			
		||||
		methodName.text = pmethod
 | 
			
		||||
		methodCall.append(methodName)
 | 
			
		||||
		methodCall.append(params)
 | 
			
		||||
		query.append(methodCall)
 | 
			
		||||
		return query
 | 
			
		||||
 
 | 
			
		||||
	def makeIqMethodCall(self,pto,pmethod,params):
 | 
			
		||||
		iq = self.xmpp.makeIqSet()
 | 
			
		||||
		iq.set('to',pto)
 | 
			
		||||
		iq.append(self.makeMethodCallQuery(pmethod,params))
 | 
			
		||||
		return iq
 | 
			
		||||
	
 | 
			
		||||
	def makeIqMethodResponse(self,pto,pid,params):
 | 
			
		||||
		iq = self.xmpp.makeIqResult(pid)
 | 
			
		||||
		iq.set('to',pto)
 | 
			
		||||
		query = self.xmpp.makeIqQuery(iq,"jabber:iq:rpc")
 | 
			
		||||
		methodResponse = ET.Element('methodResponse')
 | 
			
		||||
		methodResponse.append(params)
 | 
			
		||||
		query.append(methodResponse)
 | 
			
		||||
		return iq
 | 
			
		||||
 | 
			
		||||
	def makeIqMethodError(self,pto,id,pmethod,params,condition):
 | 
			
		||||
		iq = self.xmpp.makeIqError(id)
 | 
			
		||||
		iq.set('to',pto)
 | 
			
		||||
		iq.append(self.makeMethodCallQuery(pmethod,params))
 | 
			
		||||
		iq.append(self.xmpp['xep_0086'].makeError(condition))
 | 
			
		||||
		return iq
 | 
			
		||||
	
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
	def call_remote(self, pto, pmethod, *args):
 | 
			
		||||
		#calls a remote method. Returns the id of the Iq.
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	def _callMethod(self,xml):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	def _callResult(self,xml):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	def _callError(self,xml):
 | 
			
		||||
		pass
 | 
			
		||||
@@ -1,133 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2010 Nathanael C. Fritz
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
    
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
from __future__ import with_statement
 | 
			
		||||
from . import base
 | 
			
		||||
import logging
 | 
			
		||||
from xml.etree import cElementTree as ET
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
class old_0050(base.base_plugin):
 | 
			
		||||
	"""
 | 
			
		||||
	XEP-0050 Ad-Hoc Commands
 | 
			
		||||
	"""
 | 
			
		||||
	
 | 
			
		||||
	def plugin_init(self):
 | 
			
		||||
		self.xep = '0050'
 | 
			
		||||
		self.description = 'Ad-Hoc Commands'
 | 
			
		||||
		self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='__None__'/></iq>" % self.xmpp.default_ns, self.handler_command, name='Ad-Hoc None')
 | 
			
		||||
		self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='execute'/></iq>" % self.xmpp.default_ns, self.handler_command, name='Ad-Hoc Execute')
 | 
			
		||||
		self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='next'/></iq>" % self.xmpp.default_ns, self.handler_command_next, name='Ad-Hoc Next', threaded=True)
 | 
			
		||||
		self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='cancel'/></iq>" % self.xmpp.default_ns, self.handler_command_cancel, name='Ad-Hoc Cancel')
 | 
			
		||||
		self.xmpp.add_handler("<iq type='set' xmlns='%s'><command xmlns='http://jabber.org/protocol/commands' action='complete'/></iq>" % self.xmpp.default_ns, self.handler_command_complete, name='Ad-Hoc Complete')
 | 
			
		||||
		self.commands = {}
 | 
			
		||||
		self.sessions = {}
 | 
			
		||||
		self.sd = self.xmpp.plugin['xep_0030']
 | 
			
		||||
	
 | 
			
		||||
	def post_init(self):
 | 
			
		||||
		base.base_plugin.post_init(self)
 | 
			
		||||
		self.sd.add_feature('http://jabber.org/protocol/commands')
 | 
			
		||||
 | 
			
		||||
	def addCommand(self, node, name, form, pointer=None, multi=False):
 | 
			
		||||
		self.sd.add_item(None, name, 'http://jabber.org/protocol/commands', node)
 | 
			
		||||
		self.sd.add_identity('automation', 'command-node', name, node)
 | 
			
		||||
		self.sd.add_feature('http://jabber.org/protocol/commands', node)
 | 
			
		||||
		self.sd.add_feature('jabber:x:data', node)
 | 
			
		||||
		self.commands[node] = (name, form, pointer, multi)
 | 
			
		||||
	
 | 
			
		||||
	def getNewSession(self):
 | 
			
		||||
		return str(time.time()) + '-' + self.xmpp.getNewId()
 | 
			
		||||
	
 | 
			
		||||
	def handler_command(self, xml):
 | 
			
		||||
		in_command = xml.find('{http://jabber.org/protocol/commands}command')
 | 
			
		||||
		sessionid = in_command.get('sessionid', None)
 | 
			
		||||
		node = in_command.get('node')
 | 
			
		||||
		sessionid = self.getNewSession()
 | 
			
		||||
		name, form, pointer, multi = self.commands[node]
 | 
			
		||||
		self.sessions[sessionid] = {}
 | 
			
		||||
		self.sessions[sessionid]['jid'] = xml.get('from')
 | 
			
		||||
		self.sessions[sessionid]['to'] = xml.get('to')
 | 
			
		||||
		self.sessions[sessionid]['past'] = [(form, None)]
 | 
			
		||||
		self.sessions[sessionid]['next'] = pointer
 | 
			
		||||
		npointer = pointer
 | 
			
		||||
		if multi:
 | 
			
		||||
			actions = ['next']
 | 
			
		||||
			status = 'executing'
 | 
			
		||||
		else:
 | 
			
		||||
			if pointer is None:
 | 
			
		||||
				status = 'completed'
 | 
			
		||||
				actions = []
 | 
			
		||||
			else:
 | 
			
		||||
				status = 'executing'
 | 
			
		||||
				actions = ['complete']
 | 
			
		||||
		self.xmpp.send(self.makeCommand(xml.attrib['from'], in_command.attrib['node'], form=form, id=xml.attrib['id'], sessionid=sessionid, status=status, actions=actions))
 | 
			
		||||
	
 | 
			
		||||
	def handler_command_complete(self, xml):
 | 
			
		||||
		in_command = xml.find('{http://jabber.org/protocol/commands}command')
 | 
			
		||||
		sessionid = in_command.get('sessionid', None)
 | 
			
		||||
		pointer = self.sessions[sessionid]['next']
 | 
			
		||||
		results = self.xmpp.plugin['old_0004'].makeForm('result')
 | 
			
		||||
		results.fromXML(in_command.find('{jabber:x:data}x'))
 | 
			
		||||
		pointer(results,sessionid)
 | 
			
		||||
		self.xmpp.send(self.makeCommand(xml.attrib['from'], in_command.attrib['node'], form=None, id=xml.attrib['id'], sessionid=sessionid, status='completed', actions=[]))
 | 
			
		||||
		del self.sessions[in_command.get('sessionid')]
 | 
			
		||||
		
 | 
			
		||||
	
 | 
			
		||||
	def handler_command_next(self, xml):
 | 
			
		||||
		in_command = xml.find('{http://jabber.org/protocol/commands}command')
 | 
			
		||||
		sessionid = in_command.get('sessionid', None)
 | 
			
		||||
		pointer = self.sessions[sessionid]['next']
 | 
			
		||||
		results = self.xmpp.plugin['old_0004'].makeForm('result')
 | 
			
		||||
		results.fromXML(in_command.find('{jabber:x:data}x'))
 | 
			
		||||
		form, npointer, next = pointer(results,sessionid)
 | 
			
		||||
		self.sessions[sessionid]['next'] = npointer
 | 
			
		||||
		self.sessions[sessionid]['past'].append((form, pointer))
 | 
			
		||||
		actions = []
 | 
			
		||||
		actions.append('prev')
 | 
			
		||||
		if npointer is None:
 | 
			
		||||
			status = 'completed'
 | 
			
		||||
		else:
 | 
			
		||||
			status = 'executing'
 | 
			
		||||
			if next:
 | 
			
		||||
				actions.append('next')
 | 
			
		||||
			else:
 | 
			
		||||
				actions.append('complete')
 | 
			
		||||
		self.xmpp.send(self.makeCommand(xml.attrib['from'], in_command.attrib['node'], form=form, id=xml.attrib['id'], sessionid=sessionid, status=status, actions=actions))
 | 
			
		||||
		
 | 
			
		||||
	def handler_command_cancel(self, xml):
 | 
			
		||||
		command = xml.find('{http://jabber.org/protocol/commands}command')
 | 
			
		||||
		try:
 | 
			
		||||
			del self.sessions[command.get('sessionid')]
 | 
			
		||||
		except:
 | 
			
		||||
			pass
 | 
			
		||||
		self.xmpp.send(self.makeCommand(xml.attrib['from'], command.attrib['node'], id=xml.attrib['id'], sessionid=command.attrib['sessionid'], status='canceled'))
 | 
			
		||||
 | 
			
		||||
	def makeCommand(self, to, node, id=None, form=None, sessionid=None, status='executing', actions=[]):
 | 
			
		||||
		if not id:
 | 
			
		||||
			id = self.xmpp.getNewId()
 | 
			
		||||
		iq = self.xmpp.makeIqResult(id)
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		iq.attrib['to'] = to
 | 
			
		||||
		command = ET.Element('{http://jabber.org/protocol/commands}command')
 | 
			
		||||
		command.attrib['node'] = node
 | 
			
		||||
		command.attrib['status'] = status
 | 
			
		||||
		xmlactions = ET.Element('actions')
 | 
			
		||||
		for action in actions:
 | 
			
		||||
			xmlactions.append(ET.Element(action))
 | 
			
		||||
		if xmlactions:
 | 
			
		||||
			command.append(xmlactions)
 | 
			
		||||
		if not sessionid:
 | 
			
		||||
			sessionid = self.getNewSession()
 | 
			
		||||
		else:
 | 
			
		||||
			iq.attrib['from'] = self.sessions[sessionid]['to']
 | 
			
		||||
		command.attrib['sessionid'] = sessionid
 | 
			
		||||
		if form is not None:
 | 
			
		||||
			if hasattr(form,'getXML'):
 | 
			
		||||
				form = form.getXML()
 | 
			
		||||
			command.append(form)
 | 
			
		||||
		iq.append(command)
 | 
			
		||||
		return iq
 | 
			
		||||
@@ -1,313 +0,0 @@
 | 
			
		||||
from __future__ import with_statement
 | 
			
		||||
from . import base
 | 
			
		||||
import logging
 | 
			
		||||
#from xml.etree import cElementTree as ET
 | 
			
		||||
from .. xmlstream.stanzabase import registerStanzaPlugin, ElementBase, ET
 | 
			
		||||
from . import stanza_pubsub
 | 
			
		||||
from . xep_0004 import Form
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
log = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class xep_0060(base.base_plugin):
 | 
			
		||||
	"""
 | 
			
		||||
	XEP-0060 Publish Subscribe
 | 
			
		||||
	"""
 | 
			
		||||
 | 
			
		||||
	def plugin_init(self):
 | 
			
		||||
		self.xep = '0060'
 | 
			
		||||
		self.description = 'Publish-Subscribe'
 | 
			
		||||
 | 
			
		||||
	def create_node(self, jid, node, config=None, collection=False, ntype=None):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
 | 
			
		||||
		create = ET.Element('create')
 | 
			
		||||
		create.set('node', node)
 | 
			
		||||
		pubsub.append(create)
 | 
			
		||||
		configure = ET.Element('configure')
 | 
			
		||||
		if collection:
 | 
			
		||||
			ntype = 'collection'
 | 
			
		||||
		#if config is None:
 | 
			
		||||
		#	submitform = self.xmpp.plugin['xep_0004'].makeForm('submit')
 | 
			
		||||
		#else:
 | 
			
		||||
		if config is not None:
 | 
			
		||||
			submitform = config
 | 
			
		||||
			if 'FORM_TYPE' in submitform.field:
 | 
			
		||||
				submitform.field['FORM_TYPE'].setValue('http://jabber.org/protocol/pubsub#node_config')
 | 
			
		||||
			else:
 | 
			
		||||
				submitform.addField('FORM_TYPE', 'hidden', value='http://jabber.org/protocol/pubsub#node_config')
 | 
			
		||||
			if ntype:
 | 
			
		||||
				if 'pubsub#node_type' in submitform.field:
 | 
			
		||||
					submitform.field['pubsub#node_type'].setValue(ntype)
 | 
			
		||||
				else:
 | 
			
		||||
					submitform.addField('pubsub#node_type', value=ntype)
 | 
			
		||||
			else:
 | 
			
		||||
				if 'pubsub#node_type' in submitform.field:
 | 
			
		||||
					submitform.field['pubsub#node_type'].setValue('leaf')
 | 
			
		||||
				else:
 | 
			
		||||
					submitform.addField('pubsub#node_type', value='leaf')
 | 
			
		||||
			submitform['type'] = 'submit'
 | 
			
		||||
			configure.append(submitform.xml)
 | 
			
		||||
		pubsub.append(configure)
 | 
			
		||||
		iq = self.xmpp.makeIqSet(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is False or result is None or result['type'] == 'error': return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def subscribe(self, jid, node, bare=True, subscribee=None):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
 | 
			
		||||
		subscribe = ET.Element('subscribe')
 | 
			
		||||
		subscribe.attrib['node'] = node
 | 
			
		||||
		if subscribee is None:
 | 
			
		||||
			if bare:
 | 
			
		||||
				subscribe.attrib['jid'] = self.xmpp.boundjid.bare
 | 
			
		||||
			else:
 | 
			
		||||
				subscribe.attrib['jid'] = self.xmpp.boundjid.full
 | 
			
		||||
		else:
 | 
			
		||||
			subscribe.attrib['jid'] = subscribee
 | 
			
		||||
		pubsub.append(subscribe)
 | 
			
		||||
		iq = self.xmpp.makeIqSet(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is False or result is None or result['type'] == 'error': return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def unsubscribe(self, jid, node, bare=True, subscribee=None):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
 | 
			
		||||
		unsubscribe = ET.Element('unsubscribe')
 | 
			
		||||
		unsubscribe.attrib['node'] = node
 | 
			
		||||
		if subscribee is None:
 | 
			
		||||
			if bare:
 | 
			
		||||
				unsubscribe.attrib['jid'] = self.xmpp.boundjid.bare
 | 
			
		||||
			else:
 | 
			
		||||
				unsubscribe.attrib['jid'] = self.xmpp.boundjid.full
 | 
			
		||||
		else:
 | 
			
		||||
			unsubscribe.attrib['jid'] = subscribee
 | 
			
		||||
		pubsub.append(unsubscribe)
 | 
			
		||||
		iq = self.xmpp.makeIqSet(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is False or result is None or result['type'] == 'error': return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def getNodeConfig(self, jid, node=None): # if no node, then grab default
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
 | 
			
		||||
		if node is not None:
 | 
			
		||||
			configure = ET.Element('configure')
 | 
			
		||||
			configure.attrib['node'] = node
 | 
			
		||||
		else:
 | 
			
		||||
			configure = ET.Element('default')
 | 
			
		||||
		pubsub.append(configure)
 | 
			
		||||
		#TODO: Add configure support.
 | 
			
		||||
		iq = self.xmpp.makeIqGet()
 | 
			
		||||
		iq.append(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		#self.xmpp.add_handler("<iq id='%s'/>" % id, self.handlerCreateNodeResponse)
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is None or result == False or result['type'] == 'error':
 | 
			
		||||
			log.warning("got error instead of config")
 | 
			
		||||
			return False
 | 
			
		||||
		if node is not None:
 | 
			
		||||
			form = result.find('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}configure/{jabber:x:data}x')
 | 
			
		||||
		else:
 | 
			
		||||
			form = result.find('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}default/{jabber:x:data}x')
 | 
			
		||||
		if not form or form is None:
 | 
			
		||||
			log.error("No form found.")
 | 
			
		||||
			return False
 | 
			
		||||
		return Form(xml=form)
 | 
			
		||||
 | 
			
		||||
	def getNodeSubscriptions(self, jid, node):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
 | 
			
		||||
		subscriptions = ET.Element('subscriptions')
 | 
			
		||||
		subscriptions.attrib['node'] = node
 | 
			
		||||
		pubsub.append(subscriptions)
 | 
			
		||||
		iq = self.xmpp.makeIqGet()
 | 
			
		||||
		iq.append(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is None or result == False or result['type'] == 'error':
 | 
			
		||||
			log.warning("got error instead of config")
 | 
			
		||||
			return False
 | 
			
		||||
		else:
 | 
			
		||||
			results = result.findall('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}subscriptions/{http://jabber.org/protocol/pubsub#owner}subscription')
 | 
			
		||||
			if results is None:
 | 
			
		||||
				return False
 | 
			
		||||
			subs = {}
 | 
			
		||||
			for sub in results:
 | 
			
		||||
				subs[sub.get('jid')] = sub.get('subscription')
 | 
			
		||||
			return subs
 | 
			
		||||
 | 
			
		||||
	def getNodeAffiliations(self, jid, node):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
 | 
			
		||||
		affiliations = ET.Element('affiliations')
 | 
			
		||||
		affiliations.attrib['node'] = node
 | 
			
		||||
		pubsub.append(affiliations)
 | 
			
		||||
		iq = self.xmpp.makeIqGet()
 | 
			
		||||
		iq.append(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is None or result == False or result['type'] == 'error':
 | 
			
		||||
			log.warning("got error instead of config")
 | 
			
		||||
			return False
 | 
			
		||||
		else:
 | 
			
		||||
			results = result.findall('{http://jabber.org/protocol/pubsub#owner}pubsub/{http://jabber.org/protocol/pubsub#owner}affiliations/{http://jabber.org/protocol/pubsub#owner}affiliation')
 | 
			
		||||
			if results is None:
 | 
			
		||||
				return False
 | 
			
		||||
			subs = {}
 | 
			
		||||
			for sub in results:
 | 
			
		||||
				subs[sub.get('jid')] = sub.get('affiliation')
 | 
			
		||||
			return subs
 | 
			
		||||
 | 
			
		||||
	def deleteNode(self, jid, node):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
 | 
			
		||||
		iq = self.xmpp.makeIqSet()
 | 
			
		||||
		delete = ET.Element('delete')
 | 
			
		||||
		delete.attrib['node'] = node
 | 
			
		||||
		pubsub.append(delete)
 | 
			
		||||
		iq.append(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is not None and result is not False and result['type'] != 'error':
 | 
			
		||||
			return True
 | 
			
		||||
		else:
 | 
			
		||||
			return False
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	def setNodeConfig(self, jid, node, config):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
 | 
			
		||||
		configure = ET.Element('configure')
 | 
			
		||||
		configure.attrib['node'] = node
 | 
			
		||||
		config = config.getXML('submit')
 | 
			
		||||
		configure.append(config)
 | 
			
		||||
		pubsub.append(configure)
 | 
			
		||||
		iq = self.xmpp.makeIqSet(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is None or result['type'] == 'error':
 | 
			
		||||
			return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def setItem(self, jid, node, items=[]):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
 | 
			
		||||
		publish = ET.Element('publish')
 | 
			
		||||
		publish.attrib['node'] = node
 | 
			
		||||
		for pub_item in items:
 | 
			
		||||
			id, payload = pub_item
 | 
			
		||||
			item = ET.Element('item')
 | 
			
		||||
			if id is not None:
 | 
			
		||||
				item.attrib['id'] = id
 | 
			
		||||
			item.append(payload)
 | 
			
		||||
			publish.append(item)
 | 
			
		||||
		pubsub.append(publish)
 | 
			
		||||
		iq = self.xmpp.makeIqSet(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is None or result is False or result['type'] == 'error': return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def addItem(self, jid, node, items=[]):
 | 
			
		||||
		return self.setItem(jid, node, items)
 | 
			
		||||
 | 
			
		||||
	def deleteItem(self, jid, node, item):
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub}pubsub')
 | 
			
		||||
		retract = ET.Element('retract')
 | 
			
		||||
		retract.attrib['node'] = node
 | 
			
		||||
		itemn = ET.Element('item')
 | 
			
		||||
		itemn.attrib['id'] = item
 | 
			
		||||
		retract.append(itemn)
 | 
			
		||||
		pubsub.append(retract)
 | 
			
		||||
		iq = self.xmpp.makeIqSet(pubsub)
 | 
			
		||||
		iq.attrib['to'] = jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is None or result is False or result['type'] == 'error': return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def getNodes(self, jid):
 | 
			
		||||
		response = self.xmpp.plugin['xep_0030'].getItems(jid)
 | 
			
		||||
		items = response.findall('{http://jabber.org/protocol/disco#items}query/{http://jabber.org/protocol/disco#items}item')
 | 
			
		||||
		nodes = {}
 | 
			
		||||
		if items is not None and items is not False:
 | 
			
		||||
			for item in items:
 | 
			
		||||
				nodes[item.get('node')] = item.get('name')
 | 
			
		||||
		return nodes
 | 
			
		||||
 | 
			
		||||
	def getItems(self, jid, node):
 | 
			
		||||
		response = self.xmpp.plugin['xep_0030'].getItems(jid, node)
 | 
			
		||||
		items = response.findall('{http://jabber.org/protocol/disco#items}query/{http://jabber.org/protocol/disco#items}item')
 | 
			
		||||
		nodeitems = []
 | 
			
		||||
		if items is not None and items is not False:
 | 
			
		||||
			for item in items:
 | 
			
		||||
				nodeitems.append(item.get('node'))
 | 
			
		||||
		return nodeitems
 | 
			
		||||
 | 
			
		||||
	def addNodeToCollection(self, jid, child, parent=''):
 | 
			
		||||
		config = self.getNodeConfig(jid, child)
 | 
			
		||||
		if not config or config is None:
 | 
			
		||||
			self.lasterror = "Config Error"
 | 
			
		||||
			return False
 | 
			
		||||
		try:
 | 
			
		||||
			config.field['pubsub#collection'].setValue(parent)
 | 
			
		||||
		except KeyError:
 | 
			
		||||
			log.warning("pubsub#collection doesn't exist in config, trying to add it")
 | 
			
		||||
			config.addField('pubsub#collection', value=parent)
 | 
			
		||||
		if not self.setNodeConfig(jid, child, config):
 | 
			
		||||
			return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def modifyAffiliation(self, ps_jid, node, user_jid, affiliation):
 | 
			
		||||
		if affiliation not in ('owner', 'publisher', 'member', 'none', 'outcast'):
 | 
			
		||||
			raise TypeError
 | 
			
		||||
		pubsub = ET.Element('{http://jabber.org/protocol/pubsub#owner}pubsub')
 | 
			
		||||
		affs = ET.Element('affiliations')
 | 
			
		||||
		affs.attrib['node'] = node
 | 
			
		||||
		aff = ET.Element('affiliation')
 | 
			
		||||
		aff.attrib['jid'] = user_jid
 | 
			
		||||
		aff.attrib['affiliation'] = affiliation
 | 
			
		||||
		affs.append(aff)
 | 
			
		||||
		pubsub.append(affs)
 | 
			
		||||
		iq = self.xmpp.makeIqSet(pubsub)
 | 
			
		||||
		iq.attrib['to'] = ps_jid
 | 
			
		||||
		iq.attrib['from'] = self.xmpp.boundjid.full
 | 
			
		||||
		id = iq['id']
 | 
			
		||||
		result = iq.send()
 | 
			
		||||
		if result is None or result is False or result['type'] == 'error':
 | 
			
		||||
		    return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def addNodeToCollection(self, jid, child, parent=''):
 | 
			
		||||
		config = self.getNodeConfig(jid, child)
 | 
			
		||||
		if not config or config is None:
 | 
			
		||||
			self.lasterror = "Config Error"
 | 
			
		||||
			return False
 | 
			
		||||
		try:
 | 
			
		||||
			config.field['pubsub#collection'].setValue(parent)
 | 
			
		||||
		except KeyError:
 | 
			
		||||
			log.warning("pubsub#collection doesn't exist in config, trying to add it")
 | 
			
		||||
			config.addField('pubsub#collection', value=parent)
 | 
			
		||||
		if not self.setNodeConfig(jid, child, config):
 | 
			
		||||
			return False
 | 
			
		||||
		return True
 | 
			
		||||
 | 
			
		||||
	def removeNodeFromCollection(self, jid, child):
 | 
			
		||||
		self.addNodeToCollection(jid, child, '')
 | 
			
		||||
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0004.stanza import Form
 | 
			
		||||
from sleekxmpp.plugins.xep_0004.stanza import FormField, FieldOption
 | 
			
		||||
from sleekxmpp.plugins.xep_0004.dataforms import XEP_0004
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(XEP_0004)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
xep_0004 = XEP_0004
 | 
			
		||||
xep_0004.makeForm = xep_0004.make_form
 | 
			
		||||
xep_0004.buildForm = xep_0004.build_form
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0004.stanza.field import FormField, FieldOption
 | 
			
		||||
from sleekxmpp.plugins.xep_0004.stanza.form import Form
 | 
			
		||||
@@ -1,20 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011 Nathanael C. Fritz, Dann Martens (TOMOTON).
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0009 import stanza
 | 
			
		||||
from sleekxmpp.plugins.xep_0009.rpc import XEP_0009
 | 
			
		||||
from sleekxmpp.plugins.xep_0009.stanza import RPCQuery, MethodCall, MethodResponse
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(XEP_0009)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
xep_0009 = XEP_0009
 | 
			
		||||
@@ -1,9 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011 Nathanael C. Fritz, Dann Martens (TOMOTON).
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0009.stanza.RPC import RPCQuery, MethodCall, MethodResponse
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0012.stanza import LastActivity
 | 
			
		||||
from sleekxmpp.plugins.xep_0012.last_activity import XEP_0012
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(XEP_0012)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
xep_0004 = XEP_0012
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permissio
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0013.stanza import Offline
 | 
			
		||||
from sleekxmpp.plugins.xep_0013.offline import XEP_0013
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(XEP_0013)
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0016 import stanza
 | 
			
		||||
from sleekxmpp.plugins.xep_0016.stanza import Privacy
 | 
			
		||||
from sleekxmpp.plugins.xep_0016.privacy import XEP_0016
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(XEP_0016)
 | 
			
		||||
@@ -1,110 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp import Iq
 | 
			
		||||
from sleekxmpp.xmlstream import register_stanza_plugin
 | 
			
		||||
from sleekxmpp.plugins import BasePlugin
 | 
			
		||||
from sleekxmpp.plugins.xep_0016 import stanza
 | 
			
		||||
from sleekxmpp.plugins.xep_0016.stanza import Privacy, Item
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class XEP_0016(BasePlugin):
 | 
			
		||||
 | 
			
		||||
    name = 'xep_0016'
 | 
			
		||||
    description = 'XEP-0016: Privacy Lists'
 | 
			
		||||
    dependencies = set(['xep_0030'])
 | 
			
		||||
    stanza = stanza
 | 
			
		||||
 | 
			
		||||
    def plugin_init(self):
 | 
			
		||||
        register_stanza_plugin(Iq, Privacy)
 | 
			
		||||
 | 
			
		||||
    def plugin_end(self):
 | 
			
		||||
        self.xmpp['xep_0030'].del_feature(feature=Privacy.namespace)
 | 
			
		||||
 | 
			
		||||
    def session_bind(self, jid):
 | 
			
		||||
        self.xmpp['xep_0030'].add_feature(Privacy.namespace)
 | 
			
		||||
 | 
			
		||||
    def get_privacy_lists(self, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'get'
 | 
			
		||||
        iq.enable('privacy')
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
 | 
			
		||||
    def get_list(self, name, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'get'
 | 
			
		||||
        iq['privacy']['list']['name'] = name
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
 | 
			
		||||
    def get_active(self, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'get'
 | 
			
		||||
        iq['privacy'].enable('active')
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
 | 
			
		||||
    def get_default(self, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'get'
 | 
			
		||||
        iq['privacy'].enable('default')
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
 | 
			
		||||
    def activate(self, name, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'set'
 | 
			
		||||
        iq['privacy']['active']['name'] = name
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
 | 
			
		||||
    def deactivate(self, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'set'
 | 
			
		||||
        iq['privacy'].enable('active')
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
 | 
			
		||||
    def make_default(self, name, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'set'
 | 
			
		||||
        iq['privacy']['default']['name'] = name
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
 | 
			
		||||
    def remove_default(self, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'set'
 | 
			
		||||
        iq['privacy'].enable('default')
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
 | 
			
		||||
    def edit_list(self, name, rules, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'set'
 | 
			
		||||
        iq['privacy']['list']['name'] = name
 | 
			
		||||
        priv_list = iq['privacy']['list']
 | 
			
		||||
 | 
			
		||||
        if not rules:
 | 
			
		||||
            rules = []
 | 
			
		||||
 | 
			
		||||
        for rule in rules:
 | 
			
		||||
            if isinstance(rule, Item):
 | 
			
		||||
                priv_list.append(rule)
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            priv_list.add_item(
 | 
			
		||||
                rule['value'],
 | 
			
		||||
                rule['action'],
 | 
			
		||||
                rule['order'],
 | 
			
		||||
                itype=rule.get('type', None),
 | 
			
		||||
                iq=rule.get('iq', None),
 | 
			
		||||
                message=rule.get('message', None),
 | 
			
		||||
                presence_in=rule.get('presence_in',
 | 
			
		||||
                    rule.get('presence-in', None)),
 | 
			
		||||
                presence_out=rule.get('presence_out',
 | 
			
		||||
                    rule.get('presence-out', None)))
 | 
			
		||||
 | 
			
		||||
    def remove_list(self, name, block=True, timeout=None, callback=None):
 | 
			
		||||
        iq = self.xmpp.Iq()
 | 
			
		||||
        iq['type'] = 'set'
 | 
			
		||||
        iq['privacy']['list']['name'] = name
 | 
			
		||||
        return iq.send(block=block, timeout=timeout, callback=callback)
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2012 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0027.stanza import Signed, Encrypted
 | 
			
		||||
from sleekxmpp.plugins.xep_0027.gpg import XEP_0027
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(XEP_0027)
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.base import register_plugin
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0030 import stanza
 | 
			
		||||
from sleekxmpp.plugins.xep_0030.stanza import DiscoInfo, DiscoItems
 | 
			
		||||
from sleekxmpp.plugins.xep_0030.static import StaticDisco
 | 
			
		||||
from sleekxmpp.plugins.xep_0030.disco import XEP_0030
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
register_plugin(XEP_0030)
 | 
			
		||||
 | 
			
		||||
# Retain some backwards compatibility
 | 
			
		||||
xep_0030 = XEP_0030
 | 
			
		||||
XEP_0030.getInfo = XEP_0030.get_info
 | 
			
		||||
XEP_0030.getItems = XEP_0030.get_items
 | 
			
		||||
XEP_0030.make_static = XEP_0030.restore_defaults
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
"""
 | 
			
		||||
    SleekXMPP: The Sleek XMPP Library
 | 
			
		||||
    Copyright (C) 2010 Nathanael C. Fritz, Lance J.T. Stout
 | 
			
		||||
    This file is part of SleekXMPP.
 | 
			
		||||
 | 
			
		||||
    See the file LICENSE for copying permission.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
from sleekxmpp.plugins.xep_0030.stanza.info import DiscoInfo
 | 
			
		||||
from sleekxmpp.plugins.xep_0030.stanza.items import DiscoItems
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user