mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-08-25 17:39:23 +00:00
Compare commits
492 Commits
alpha9
...
v2022.12.6
Author | SHA1 | Date | |
---|---|---|---|
2323c3cac5 | |||
e90c370e73 | |||
cadcc56182 | |||
619f58ad90 | |||
c480554e01 | |||
6da81a9734 | |||
b559726535 | |||
768f0bc396 | |||
5bbf069d61 | |||
d177ef5be2 | |||
b6dd539dc6 | |||
fabca1207d | |||
bf4c7ff7c7 | |||
8d2fb59ba8 | |||
b7497791b4 | |||
48730ead63 | |||
98ecd000a9 | |||
4a9098021f | |||
8850e5fdde | |||
e42bd85274 | |||
d3914a4e34 | |||
73de8d4f49 | |||
ce458a8d4d | |||
149ce51f49 | |||
2fe9c35c0b | |||
39fb5b4830 | |||
71ca547abe | |||
1c5c1067e6 | |||
df4d3eb0e6 | |||
927bbae1be | |||
cbc4fd0632 | |||
10d4d47a17 | |||
52d64d86d8 | |||
2ab61ebee6 | |||
3ad01d1ab0 | |||
7835e09c5b | |||
4c5d2b5e04 | |||
8f72ee97c9 | |||
aebdcae9cf | |||
3b5ef02def | |||
35599ee0ef | |||
6e03578e86 | |||
7cbf873db5 | |||
fefd88b71c | |||
7c80c9d842 | |||
f5e52c6387 | |||
4c43f82b60 | |||
2caaaa9d87 | |||
3fa39c712e | |||
252a93f82d | |||
f5328379e8 | |||
2e8c8c6db4 | |||
862dbd0b8a | |||
120da217f5 | |||
035de92496 | |||
2a0e73ad33 | |||
701a557357 | |||
de1d94e679 | |||
64d5b7e684 | |||
2c9048618f | |||
![]() |
d66f4a2640 | ||
bfbb280c27 | |||
cad7c9a9fd | |||
81ff530a71 | |||
39fc982665 | |||
803f5fbe89 | |||
0d1d4c887d | |||
f8f13be6d3 | |||
5f645508ba | |||
3a3cb3963c | |||
2c298577cc | |||
97815f807a | |||
f24f97baae | |||
2a10f029f0 | |||
3deffa57de | |||
d6985be896 | |||
0aad2f0ab3 | |||
f151d6554d | |||
62d6ae2277 | |||
b405e384c8 | |||
7aa986163b | |||
59409e61a5 | |||
edbc74262a | |||
e07efa46b3 | |||
bedb2e2a4f | |||
96b5eec8e0 | |||
c6433d8655 | |||
c0654658b5 | |||
d71d3695eb | |||
4b6a7c5d83 | |||
368e089639 | |||
33647da6e8 | |||
ca39db649b | |||
07dc813cb6 | |||
a852a429f4 | |||
1e3a0d9b2e | |||
9959ac24d9 | |||
90f9f18deb | |||
6983d11b73 | |||
cd5b71a26e | |||
aa3ca82f25 | |||
bf9b8a4f46 | |||
2be460b662 | |||
1d4057ac5b | |||
b9731a3c75 | |||
d53decb165 | |||
02b8330ca0 | |||
12046c1f56 | |||
6f69426f03 | |||
c8c242a27f | |||
60daa548ca | |||
40989a54ed | |||
87f2976419 | |||
b6b81e2b36 | |||
dfcd63b9b6 | |||
23af944fba | |||
cf9add1fc9 | |||
a63f19a70f | |||
8ad266ad1b | |||
b593071364 | |||
0e814a765a | |||
2c7eab60a8 | |||
d43738a2ec | |||
0f885712b6 | |||
14a10989e5 | |||
d5253f651b | |||
31e901b000 | |||
26e7ff009f | |||
1ded773e84 | |||
b8637ba8ca | |||
4dc4f46b84 | |||
e00ec84df3 | |||
8dd122cfb2 | |||
dcfacf8cdd | |||
bc1522833c | |||
4b7382e61f | |||
585d8e2b0c | |||
f34829d72d | |||
![]() |
fd1d60b815 | ||
![]() |
31e194a038 | ||
![]() |
e25712920a | ||
![]() |
27867a1961 | ||
![]() |
1425dcd313 | ||
![]() |
b9cff1a9c9 | ||
fc1ed54963 | |||
![]() |
442abe82db | ||
1b693cd798 | |||
![]() |
8426d8851f | ||
![]() |
eca5aa7bfe | ||
8116d98691 | |||
1b498a99bd | |||
1a4e594549 | |||
![]() |
2b0172f02f | ||
2d2c84fefe | |||
![]() |
0bef872070 | ||
b233842f5c | |||
0202b704da | |||
7d3ac47d55 | |||
e2ba61701f | |||
![]() |
8032f5cf75 | ||
![]() |
96f5d0e426 | ||
0ba71c985d | |||
c6cbe3360b | |||
ac80e039b2 | |||
2039597098 | |||
74fd4bfadf | |||
c374663b7c | |||
0f3d7d8747 | |||
0a395af3a9 | |||
![]() |
f181c5d1cd | ||
![]() |
204b9ebc02 | ||
0a479b55ed | |||
![]() |
eb0c3a650a | ||
829506acf5 | |||
14ee87b25a | |||
ebdf2e21bb | |||
![]() |
30a944fc61 | ||
![]() |
5c0af2fc01 | ||
e470498e56 | |||
fa2d2d9d78 | |||
b9794806d7 | |||
1e686cffba | |||
0f624c7dbe | |||
76a5c960e5 | |||
aab8aafefc | |||
015cf9eca3 | |||
769436abf7 | |||
b2da25dd61 | |||
03f59064d5 | |||
9afd6774f2 | |||
a1929ff1d3 | |||
4b627a13ff | |||
f9f7a32f90 | |||
f01ad5abb7 | |||
6fcd0274a9 | |||
654b34c8e1 | |||
02e1793d08 | |||
6e80b320c9 | |||
83c9db573e | |||
3aee5e8900 | |||
![]() |
a88af08181 | ||
79098cc730 | |||
d12e3aa335 | |||
![]() |
1d8fcf9166 | ||
3702405f8c | |||
7ce55c427e | |||
508b798bee | |||
53ac43a8b2 | |||
![]() |
22b8d91612 | ||
![]() |
4f619759e6 | ||
![]() |
0ac6f49379 | ||
![]() |
b332902b91 | ||
a138b8c02e | |||
c89dff053d | |||
018095752b | |||
bd90902e3b | |||
8bf9c6519e | |||
bed8e26204 | |||
fa9ebea836 | |||
be8d82a65f | |||
ab979e2623 | |||
20ad268e5a | |||
![]() |
83c9a7f0f9 | ||
9d90d91cfd | |||
bbf1356c89 | |||
485b4c3c6c | |||
b35cdbd7b4 | |||
67d15d8fe1 | |||
![]() |
3bd274db0c | ||
6147ca8658 | |||
![]() |
7833522b56 | ||
dbafeb9872 | |||
c6865a7742 | |||
fcb2ce119b | |||
9f74d568f0 | |||
e3137f4c3d | |||
3f58112a61 | |||
307085b0d5 | |||
44ea77b605 | |||
5e47e30bc3 | |||
![]() |
c6a2ba6a31 | ||
085c9038b5 | |||
af4e72ee27 | |||
9322241747 | |||
116a0288d4 | |||
d0322e7131 | |||
000cf1aff1 | |||
2f0515a449 | |||
ac9efd7550 | |||
![]() |
540a99f02f | ||
8e95843634 | |||
cf56b518d6 | |||
1262a9d784 | |||
7c85ceced1 | |||
![]() |
3d452b3db8 | ||
950ece43d5 | |||
ac0e7380b0 | |||
6e0a94355f | |||
e43ddad678 | |||
c048c3ff32 | |||
301e3d4361 | |||
7a78accd1f | |||
d7afa77c49 | |||
e7a30b418a | |||
a645e0b964 | |||
e8287c75cc | |||
6a839baed7 | |||
8924f787d4 | |||
b81aff7f8d | |||
1dfe256cfe | |||
ee8e4b1d8b | |||
0317eff6a5 | |||
793bd2cf5b | |||
![]() |
c0ee1d2c29 | ||
![]() |
9e6740253c | ||
c08eb499e1 | |||
![]() |
5d0e1f38ab | ||
1d60751dbd | |||
![]() |
b23915e546 | ||
c8da3bdfdb | |||
ebf7916ae0 | |||
33338ba09a | |||
8b50f3138c | |||
ae28c374d5 | |||
5a2786967b | |||
ed765117a5 | |||
911e8d3cfd | |||
b6ae9f4b79 | |||
a74825a0f6 | |||
445c33f003 | |||
81963dbb53 | |||
b4526c12c9 | |||
b2f9aef7f7 | |||
95063cd472 | |||
4434a5b971 | |||
2de9f8f9b3 | |||
a6ecd37547 | |||
03c330c0a4 | |||
ab1a0946a4 | |||
1f253221b3 | |||
58ba722bd7 | |||
416151570c | |||
af4594f16c | |||
a47fa31346 | |||
40e13250ca | |||
0bd366c539 | |||
b67fc0ff38 | |||
86a2eb7c0d | |||
78c10b38e5 | |||
![]() |
cfd4fd12d3 | ||
![]() |
806111c36e | ||
7bfbadc254 | |||
3ccb3a5be5 | |||
![]() |
f264f3807f | ||
3902a57d6b | |||
![]() |
485e5ecbd1 | ||
![]() |
f7a50d22e2 | ||
43b1a834d1 | |||
d6571a95cb | |||
4ba2753b79 | |||
6951541193 | |||
b329ac8e3e | |||
538d6137d0 | |||
622b0e6128 | |||
![]() |
0e91ca3d4d | ||
![]() |
8abcb3623d | ||
b3bf0ab8e6 | |||
eea059b905 | |||
e9f6fd529e | |||
b0cfc5978c | |||
77d13fdc28 | |||
514e66411d | |||
d9f4b86d91 | |||
a6964a1bb9 | |||
a43101e694 | |||
![]() |
9e7542f513 | ||
![]() |
6346651edf | ||
1e2464c4fa | |||
dbecf341ec | |||
605868eff9 | |||
8fed52118f | |||
15d0f4c65e | |||
a2393fe3e9 | |||
80adf381c9 | |||
269db95fe3 | |||
cfc25eb89a | |||
2b6efef831 | |||
f0456af656 | |||
6d505c6fe7 | |||
38e3274adc | |||
2c70fe46b7 | |||
1c8ee1a64f | |||
076761b9dd | |||
556ffd832b | |||
cedb290956 | |||
66bf95ee62 | |||
4f0db5537e | |||
![]() |
7c5c191deb | ||
![]() |
0cf0a64f40 | ||
714d849884 | |||
a80184bf20 | |||
![]() |
46fb00e609 | ||
![]() |
4ddb406c8d | ||
6b9540a0a8 | |||
5687cf6a62 | |||
1fd2b5914b | |||
924f5d8e9f | |||
13c441557b | |||
![]() |
2c4ec7b1c0 | ||
c4b7c35c7f | |||
2d46315de9 | |||
6904c153d4 | |||
8b06437cad | |||
c3261a4e2c | |||
9f7892ff03 | |||
ab44ce6fcb | |||
ed80558273 | |||
60a67947e6 | |||
8a8f1998ac | |||
cd415ba673 | |||
f9e58b5724 | |||
![]() |
94ca935b2f | ||
84fa2fad91 | |||
ff0a2b5692 | |||
b39b732a93 | |||
b04a1c74a7 | |||
ffb11b8226 | |||
5a6dc23524 | |||
0e2ff4de8a | |||
36340d0596 | |||
92ec178754 | |||
5eb942981c | |||
6739045cce | |||
307ed093af | |||
d11fc44772 | |||
a3e5eec6de | |||
41a0935121 | |||
0b03e7505f | |||
![]() |
81c364c4e1 | ||
![]() |
483b196203 | ||
![]() |
b512c69447 | ||
2c1608322e | |||
c6bb851bce | |||
![]() |
66581f8b1c | ||
![]() |
c6a3a44c21 | ||
bd25cfa59b | |||
![]() |
39a02ea33a | ||
f672dca1cb | |||
19c63b7b07 | |||
e23a52e38f | |||
![]() |
d888563fda | ||
a5ba80feee | |||
528ecc2a33 | |||
3519746078 | |||
ef79e0696e | |||
b9ee0dae5b | |||
f31575a733 | |||
e451bbd5e9 | |||
f7f303929e | |||
9f48784ce4 | |||
cb1312d0c9 | |||
a82efd4dcc | |||
72e6d030d5 | |||
d222740887 | |||
2b059ee42e | |||
daac312658 | |||
b23be9c896 | |||
61b0dc34b8 | |||
c5d13369eb | |||
856ecf5eb9 | |||
e3e0ac9457 | |||
fccf02794c | |||
34c1f69ec1 | |||
7326ff88f9 | |||
![]() |
a8d876a7b7 | ||
![]() |
89fa6435b4 | ||
![]() |
d1bd393be2 | ||
301bd5fd39 | |||
![]() |
a2f25bfbb5 | ||
286e030f40 | |||
d8fca3b31a | |||
0c27427843 | |||
dfdbe3c5f4 | |||
![]() |
2222a97451 | ||
fbe93ea4be | |||
4bcae1aa97 | |||
4cabf5b9cd | |||
a9a4189295 | |||
c7b6d69518 | |||
65512a9862 | |||
![]() |
17ea8af050 | ||
![]() |
43578a32eb | ||
d863aafa8c | |||
5bce84b786 | |||
9eab9ad5f0 | |||
7c34204d17 | |||
3a5c1c10d3 | |||
f9864a887d | |||
3d8519313e | |||
f4ecf10885 | |||
c67b415934 | |||
10511d3022 | |||
![]() |
ddc80a29fd | ||
9ea36a26d2 | |||
97286496fc | |||
![]() |
6436af76f5 | ||
![]() |
576b5064c0 | ||
![]() |
342265b3c0 | ||
![]() |
54938ecb6c | ||
![]() |
7aff8252d2 | ||
![]() |
9c680130f7 | ||
24d1ad093d | |||
b2b9cd810f | |||
582be54dea | |||
ff0fbeafa3 | |||
e314cf0599 | |||
![]() |
e7b72112cf | ||
![]() |
70c095febe | ||
6119b029f8 | |||
b74cd9a73d | |||
8ff6809f08 | |||
39af9d8623 | |||
3688d7548c | |||
07f9afb14e | |||
de12dadac2 | |||
877c909482 | |||
![]() |
1206aba83b | ||
![]() |
fcd631b2de | ||
![]() |
86130954d7 | ||
![]() |
23a56c637d | ||
![]() |
d5ac0db67b | ||
![]() |
0e4b133858 |
@@ -1,6 +1,6 @@
|
|||||||
variables:
|
variables:
|
||||||
GIT_SUBMODULE_STRATEGY: recursive
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
PYTHON: "C:\\python38\\python.exe"
|
PYTHON: "C:\\python310\\python.exe"
|
||||||
NSIS: "C:\\program files (x86)\\nsis\\makensis.exe"
|
NSIS: "C:\\program files (x86)\\nsis\\makensis.exe"
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
@@ -8,7 +8,7 @@ stages:
|
|||||||
- make_installer
|
- make_installer
|
||||||
- upload
|
- upload
|
||||||
|
|
||||||
snapshot32:
|
twblue32:
|
||||||
tags:
|
tags:
|
||||||
- shared-windows
|
- shared-windows
|
||||||
- windows
|
- windows
|
||||||
@@ -17,11 +17,11 @@ snapshot32:
|
|||||||
- Set-Variable -Name "time" -Value (date -Format "%H:%m")
|
- Set-Variable -Name "time" -Value (date -Format "%H:%m")
|
||||||
- echo ${time}
|
- echo ${time}
|
||||||
- echo "started by ${GITLAB_USER_NAME}"
|
- echo "started by ${GITLAB_USER_NAME}"
|
||||||
- choco install python --version 3.8.10 -y -ForceX86
|
- choco install python --version 3.10.8 -y -ForceX86
|
||||||
- '&$env:PYTHON -V'
|
- '&$env:PYTHON -V'
|
||||||
- '&$env:PYTHON -m pip install --upgrade pip'
|
- '&$env:PYTHON -m pip install --upgrade pip'
|
||||||
|
- '&$env:PYTHON -m pip install --upgrade https://github.com/josephsl/wxpy32whl/blob/main/wxPython-4.2.0-cp310-cp310-win32.whl?raw=true'
|
||||||
- '&$env:PYTHON -m pip install --upgrade -r requirements.txt'
|
- '&$env:PYTHON -m pip install --upgrade -r requirements.txt'
|
||||||
- '&$env:PYTHON -m pip uninstall enum34 -y'
|
|
||||||
stage: build
|
stage: build
|
||||||
interruptible: true
|
interruptible: true
|
||||||
script:
|
script:
|
||||||
@@ -30,6 +30,8 @@ snapshot32:
|
|||||||
- '&$env:PYTHON documentation_importer.py'
|
- '&$env:PYTHON documentation_importer.py'
|
||||||
- cd ..\src
|
- cd ..\src
|
||||||
- '&$env:PYTHON ..\doc\generator.py'
|
- '&$env:PYTHON ..\doc\generator.py'
|
||||||
|
- '&$env:PYTHON write_version_data.py'
|
||||||
|
- New-Item "appkeys.py" -ItemType File -Value "twitter_api_key='$TWITTER_API_KEY'`ntwitter_api_secret='$TWITTER_API_SECRET'"
|
||||||
- '&$env:PYTHON setup.py build'
|
- '&$env:PYTHON setup.py build'
|
||||||
- cd ..
|
- cd ..
|
||||||
- mkdir artifacts
|
- mkdir artifacts
|
||||||
@@ -37,7 +39,9 @@ snapshot32:
|
|||||||
- '&$env:PYTHON make_archive.py'
|
- '&$env:PYTHON make_archive.py'
|
||||||
- cd ..
|
- cd ..
|
||||||
- mv src/dist artifacts/TWBlue
|
- mv src/dist artifacts/TWBlue
|
||||||
- move src/twblue.zip artifacts/twblue_snapshot_x86.zip
|
- move src/twblue.zip artifacts/twblue_x86.zip
|
||||||
|
# Move the generated script nsis file to artifacts, so we won't need python when generating the installer.
|
||||||
|
- move scripts/twblue.nsi artifacts/twblue.nsi
|
||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
artifacts:
|
artifacts:
|
||||||
@@ -45,7 +49,7 @@ snapshot32:
|
|||||||
- artifacts
|
- artifacts
|
||||||
expire_in: 1 day
|
expire_in: 1 day
|
||||||
|
|
||||||
snapshot64:
|
twblue64:
|
||||||
tags:
|
tags:
|
||||||
- shared-windows
|
- shared-windows
|
||||||
- windows
|
- windows
|
||||||
@@ -54,7 +58,7 @@ snapshot64:
|
|||||||
- Set-Variable -Name "time" -Value (date -Format "%H:%m")
|
- Set-Variable -Name "time" -Value (date -Format "%H:%m")
|
||||||
- echo ${time}
|
- echo ${time}
|
||||||
- echo "started by ${GITLAB_USER_NAME}"
|
- echo "started by ${GITLAB_USER_NAME}"
|
||||||
- choco install python --version 3.8.10 -y
|
- choco install python --version 3.10.8 -y
|
||||||
- '&$env:PYTHON -V'
|
- '&$env:PYTHON -V'
|
||||||
- '&$env:PYTHON -m pip install --upgrade pip'
|
- '&$env:PYTHON -m pip install --upgrade pip'
|
||||||
- '&$env:PYTHON -m pip install --upgrade -r requirements.txt'
|
- '&$env:PYTHON -m pip install --upgrade -r requirements.txt'
|
||||||
@@ -66,6 +70,8 @@ snapshot64:
|
|||||||
- '&$env:PYTHON documentation_importer.py'
|
- '&$env:PYTHON documentation_importer.py'
|
||||||
- cd ..\src
|
- cd ..\src
|
||||||
- '&$env:PYTHON ..\doc\generator.py'
|
- '&$env:PYTHON ..\doc\generator.py'
|
||||||
|
- '&$env:PYTHON write_version_data.py'
|
||||||
|
- New-Item "appkeys.py" -ItemType File -Value "twitter_api_key='$TWITTER_API_KEY'`ntwitter_api_secret='$TWITTER_API_SECRET'"
|
||||||
- '&$env:PYTHON setup.py build'
|
- '&$env:PYTHON setup.py build'
|
||||||
- cd ..
|
- cd ..
|
||||||
- mkdir artifacts
|
- mkdir artifacts
|
||||||
@@ -73,7 +79,7 @@ snapshot64:
|
|||||||
- '&$env:PYTHON make_archive.py'
|
- '&$env:PYTHON make_archive.py'
|
||||||
- cd ..
|
- cd ..
|
||||||
- mv src/dist artifacts/TWBlue64
|
- mv src/dist artifacts/TWBlue64
|
||||||
- move src/twblue.zip artifacts/twblue_snapshot_x64.zip
|
- move src/twblue.zip artifacts/twblue_x64.zip
|
||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
artifacts:
|
artifacts:
|
||||||
@@ -95,9 +101,10 @@ generate_versions:
|
|||||||
script:
|
script:
|
||||||
- move artifacts/TWBlue scripts/
|
- move artifacts/TWBlue scripts/
|
||||||
- move artifacts/TWBlue64 scripts/
|
- move artifacts/TWBlue64 scripts/
|
||||||
|
- move artifacts/twblue.nsi scripts/installer.nsi
|
||||||
- cd scripts
|
- cd scripts
|
||||||
- '&$env:NSIS twblue_snapshot.nsi'
|
- '&$env:NSIS installer.nsi'
|
||||||
- move twblue_snapshot_setup.exe ../artifacts
|
- move twblue_setup.exe ../artifacts
|
||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
artifacts:
|
artifacts:
|
||||||
|
19
README.md
19
README.md
@@ -21,6 +21,15 @@ See [TWBlue's webpage](http://twblue.es) for more details.
|
|||||||
|
|
||||||
This document describes how to run tw blue from source and how to build a binary version which doesn't need Python and the other dependencies to run.
|
This document describes how to run tw blue from source and how to build a binary version which doesn't need Python and the other dependencies to run.
|
||||||
|
|
||||||
|
### Generating application keys
|
||||||
|
|
||||||
|
In order to communicate with Twitter, you will need to generate a set of API keys in their [developer portal](https://developer.twitter.com/en/portal/dashboard) (If you haven't signed up, [visit this site to register as a developer](https://developer.twitter.com/en/docs/twitter-api/getting-started/getting-access-to-the-twitter-api)) and create a module called appkeys.py, within the src directory, with the following content, replacing the example values with your set of API keys:
|
||||||
|
|
||||||
|
```
|
||||||
|
twitter_api_key='xxxxxxxxxx'
|
||||||
|
twitter_api_secret='xxxxxxxxxx'
|
||||||
|
```
|
||||||
|
|
||||||
### Required dependencies.
|
### Required dependencies.
|
||||||
|
|
||||||
Although most dependencies can be found in the windows-dependencies directory, we provide links to their official websites. If you are cloning with git, don't forget to initialize and update the submodules to get the windows-dependencies folder. You can use these two commands to perform this task from git bash:
|
Although most dependencies can be found in the windows-dependencies directory, we provide links to their official websites. If you are cloning with git, don't forget to initialize and update the submodules to get the windows-dependencies folder. You can use these two commands to perform this task from git bash:
|
||||||
@@ -31,18 +40,22 @@ Although most dependencies can be found in the windows-dependencies directory, w
|
|||||||
|
|
||||||
#### Dependencies packaged in windows installers
|
#### Dependencies packaged in windows installers
|
||||||
|
|
||||||
* [Python,](https://python.org) version 3.8.7
|
* [Python,](https://python.org) version 3.10.8
|
||||||
If you want to build both x86 and x64 binaries, you can install python x86 to C:\python38 and python x64 to C:\python38x64, for example.
|
If you want to build both x86 and x64 binaries, you can install python x64 to C:\python310 and python x86 to C:\python310-32, for example.
|
||||||
|
|
||||||
#### Dependencies that must be installed using pip
|
#### Dependencies that must be installed using pip
|
||||||
|
|
||||||
Python installs a tool called Pip that allows to install packages in a simple way. You can find it in the python scripts directory. To install packages using Pip, you have to navigate to the scripts directory using a command prompt, for example:
|
Python installs a tool called Pip that allows to install packages in a simple way. You can find it in the python scripts directory. To install packages using Pip, you have to navigate to the scripts directory using a command prompt, for example:
|
||||||
|
|
||||||
`cd C:\python37x64\scripts`
|
`cd C:\python310\scripts`
|
||||||
|
|
||||||
You can also add the scripts folder to your path environment variable or choose the corresponding option when installing Python.
|
You can also add the scripts folder to your path environment variable or choose the corresponding option when installing Python.
|
||||||
Note: pip and setuptools are included in the Python installer since version 2.7.9.
|
Note: pip and setuptools are included in the Python installer since version 2.7.9.
|
||||||
|
|
||||||
|
Note: If you are using Python for 32-bit systems, you will need to install WXPython for 32-bits before running the command for installing everything else. You can do so by running the following command:
|
||||||
|
|
||||||
|
`pip install --upgrade https://github.com/josephsl/wxpy32whl/blob/main/wxPython-4.2.0-cp310-cp310-win32.whl?raw=true`
|
||||||
|
|
||||||
Pip is able to install packages listed in a special text file, called the requirements file. To install all remaining dependencies, perform the following command:
|
Pip is able to install packages listed in a special text file, called the requirements file. To install all remaining dependencies, perform the following command:
|
||||||
|
|
||||||
`pip install -r requirements.txt`
|
`pip install -r requirements.txt`
|
||||||
|
@@ -39,5 +39,5 @@ florian Ionașcu
|
|||||||
Christian Leo Mameli
|
Christian Leo Mameli
|
||||||
Natalia Hedlund (Наталья Хедлунд)
|
Natalia Hedlund (Наталья Хедлунд)
|
||||||
Valeria (Валерия)
|
Valeria (Валерия)
|
||||||
Oreonan
|
Corentin Bacqué-Cazenave
|
||||||
Artem Plaksin (maniyax)
|
Artem Plaksin (maniyax)
|
||||||
|
101
doc/changelog.md
101
doc/changelog.md
@@ -1,7 +1,104 @@
|
|||||||
TWBlue Changelog
|
TWBlue Changelog
|
||||||
|
|
||||||
## changes in this version
|
## changes in this version
|
||||||
|
|
||||||
|
Most of all changes in this release are focused on adding Mastodon support to TWBlue. The features present to handle Twitter should not have been altered in any way. We were not intended to release this version so soon, but unfortunately, Twitter started to present issues in some regions with one particular API endpoint we were using, making impossible for everyone in such regions to use the application. We will release more updates to fix any possible issue regarding Twitter API, but please take into account that this is sometimes an issue happening in Twitter's servers and while we do our best to make TWBlue work despite those problems, you might encounter glitches from time to time.
|
||||||
|
|
||||||
|
* TWBlue now builds with Python 3.10.8. ([#493](https://github.com/MCV-Software/TWBlue/issues/493))
|
||||||
|
* This change also drops support for Windows 7.
|
||||||
|
* The TWBlue interface has not been translated yet, as we are releasing this update to fix an important Twitter issue for some regions.
|
||||||
|
* Twitter sessions should be able to be opened properly again in TWBlue, in regions where it didn't work since last week.
|
||||||
|
* It is now possible to log in to instances of mastodon, hometown and similar software (Pleroma should work as well, although it has not been tested at this time). From the session manager, clicking on the “new account” button will bring up a menu from which you can select whether you want to log in to Twitter or Mastodon. For instances that have a different character limit than the one set by Mastodon, TWBlue will detect the new limit and adjust the dialogs to allow you to use it correctly.
|
||||||
|
* Most of the TWBlue GUI has been adapted so that the buffers reflect the change of social network (in mastodon, for example, the buttons to write posts say post instead of tweet). However, the menu bar has not yet been updated. This means that most of the options still refer to Twitter, although they can be used with mastodon accounts. For example, if you select the “tweet” menu in the menu bar, and then select the “Retweet” option, TWBlue will actually do a “boost” if the buffer you are in is a Mastodon account buffer.
|
||||||
|
* Keystrokes for the invisible interface also refer to terms used in Twitter, but can be applied to Mastodon as well.
|
||||||
|
* There are some features, within TWBlue, that are not yet compatible with mastodon accounts. These are as follows:
|
||||||
|
* User autocompletion.
|
||||||
|
* Currently, it is not possible to update account settings for mastodon sessions. However, if you know how to edit configuration files, you can close TWBlue, change your session file with any text editor and restart the application to update what you want.
|
||||||
|
* The template editor is not yet available for mastodon accounts.
|
||||||
|
* Filters have not yet been implemented in TWBlue mastodon support.
|
||||||
|
* User aliases are not implemented yet.
|
||||||
|
* It is not possible to view a user’s profile, nor edit your own, for now. However, you can use the keystroke to open the item in the browser when focusing a user to access their profile website. This only works in buffers where users are listed.
|
||||||
|
* You cannot manage lists in TWBlue at the moment.
|
||||||
|
* Most of the buffers planned for mastodon should just work. Among those currently tested are: home (main timeline for the logged-in user), Local (public posts for the instance), federated (public posts for all federating instances), mentions, direct messages, sent posts, favorites, bookmarks, followers, following, blocked users, muted users, user searches and timelines for users.
|
||||||
|
* The difference between favorites and bookmarks is that the author of the post can see who has marked his posts as favorites, but bookmarks are completely private. In any buffer containing mastodon posts, except direct messages, the GUI will display an option to add the post to favorites or bookmarks.
|
||||||
|
* Direct messages in mastodon are posts, exactly like normal posts, but with their privacy setting set so that they can only be seen by the accounts that are mentioned. In the direct message buffer, a conversation will appear for each item in the buffer. The conversation represents a thread of messages, but TWBlue can only display the last of the messages sent. This is similar to what happens on platforms like Telegram, where you can only see the list of conversations at the beginning. To see the entire thread of direct messages present in a conversation, you can use the command to open the conversation, or go to the “tweet” menu in the menu bar, and then towards the “view conversation” option. This will create a new conversation buffer that will be located just after the direct messages buffer (for the GUI, the buffer will be located just inside the direct messages buffer in the buffer tree). When a private post appears (whose visibility only allows the mentioned accounts to see it), TWBlue will display that post in the home buffer, in mentions and also will update/create the conversation with that item. This is because Mastodon does not differentiate between a private message and a normal post. You can reply to the post in any buffer to continue the conversation. If you reply to any post, the privacy set in the original post is maintained by default, but can also be changed.
|
||||||
|
* The buffer showing the federated timeline has been disabled from settings. This is because on servers that federate with many instances it can load many posts in a very short time. To enable this buffer, for now, edit the TWBlue configuration while the application is closed, and add the “federated” buffer in the option called “buffer_order”. As soon as buffers can be shown or hidden, this process can be done through the GUI.
|
||||||
|
* There is a Streaming API that allows the elements for the start buffers, mentions, direct messages, sent posts and followers to appear in real time. This feature is implemented by default and should also just work.
|
||||||
|
* Timelines for users only allow to get all posts from users who are in the same instance. For users belonging to other instances, you can get the posts that have been downloaded to your instance since your instance “knows” the remote user.
|
||||||
|
* Timelines for followers and following can be fully retrieved only for users belonging to the same instance. Remote users may yield unclear results.
|
||||||
|
* You can search by users (by opening a search and selecting the “users” radio button). The search can be done by local users, such as twblue, or by remote users, such as @twblue@maaw.social.
|
||||||
|
* In all buffers, a maximum of 40 items are retrieved per load, but more can be retrieved by using the option to load more items in the buffer.
|
||||||
|
* In post buffers, you can do most of the actions already supported in TWBlue (boost, add/remove from favorites or bookmarks, reply, send message to user, open post URL, play audio or video, open post on web, view conversation, open action dialog for user).
|
||||||
|
* In user buffers, you can send private message to the user, and open user actions dialog, which in turn allows you to follow/unfollow, block/unblock and mute/unmute.
|
||||||
|
* When writing posts, it is possible to attach up to 4 images, 4 givs, or even a video, poll, or audio. It is also possible to add the “sensitive content” tag to posts, change privacy and write a content warning text. It is possible to create threads using the “add post” button.
|
||||||
|
* When replying to a post, TWBlue will place the username of all participants in the item you reply to. The privacy options will default to those of the original post.
|
||||||
|
|
||||||
|
## Changes in version 2022.8.28
|
||||||
|
|
||||||
|
* the user autocompletion feature has been completely rewritten to be easier to use, particularly for people with many followers/following users:
|
||||||
|
* In the account settings dialog, there's a button that opens up a new dialog that allows you to "scan" your account in order to add all users from your followers/following list. This process will read your data directly from Twitter and depending in the amount of people you have in your account it might take too many API calls. Please use it with caution. You can, for example, do the process separately for your followers/following people so it will be easier to handle, in case you have a massive amount of people. If TWBlue is unable to complete the scan, you will see an error and will be prompted to try again in 15 minutes, once your API calls have refreshed.
|
||||||
|
* It is possible to use the user autocompletion functionality in dialogs where you can select an user, for example when adding or removing someone from a list, or displaying lists for someone.
|
||||||
|
* Implemented a new setting, available in the account settings dialog, that allows to hide emojis in twitter usernames.
|
||||||
|
* TWBlue should be able to sort conversations in a more logical way. This should make it easier to follow a long thread in Twitter.
|
||||||
|
* When opening a thread, TWBlue should be able to load the right conversation if the original tweet from where the thread was loaded was a retweet.
|
||||||
|
* TWBlue will restart the Streaming subsystem every time there are changes to followed, muted or blocked users within the application.
|
||||||
|
* Fixed error when attempting to mention an user by using the "mention" button in any people buffer. Now tweets should be posted normally.
|
||||||
|
* Fixed error when loading other user lists. ([#465](https://github.com/MCV-Software/TWBlue/issues/465))
|
||||||
|
* Fixed an issue that was making TWBlue to display incorrectly some retweets of quoted tweets.
|
||||||
|
* If TWBlue is unable to open a timeline for someone who has blocked you, this will be reported in a dialog. ([#485,](https://github.com/mcv-software/twblue/issues/485))
|
||||||
|
* Added "find a string in the currently focused buffer" action into Windows 10 and windows 11 keymap. ([#476](https://github.com/MCV-Software/TWBlue/pull/476))
|
||||||
|
|
||||||
|
## changes in version 22.2.23
|
||||||
|
|
||||||
|
* We have added Experimental support for templates in the invisible interface. The GUI will remain unchanged for now:
|
||||||
|
* Each object (tweet, received direct message, sent direct message and people) has its own template in the settings. You can edit those templates from the account settings dialog, in the new "templates" tab.
|
||||||
|
* Every template is composed of the group of variables you want to display for each object. Each variable will start with a dollar sign ($) and cannot contain spaces or special characters. Templates can include arbitrary text that will not be processed. When editing the example templates, you can get an idea of the variables that are available for each object by using the template editing dialog. When you press enter on a variable from the list of available variables, it will be added to the template automatically. When you try to save a template, TWBlue will warn you if the template is incorrectly formatted or if it includes variables that do not exist in the information provided by objects. It is also possible to return to default values from the same dialog when editing a template.
|
||||||
|
* TWBlue can display image descriptions within Tweet templates. For that, you can use the $image_description variable in your template.
|
||||||
|
* We have restored conversation and threads support powered by Twitter API V2 thanks to a set of improvements we have done in the application, as well as more generous limits to Tweet monthly cap by Twitter.
|
||||||
|
* In the Windows 11 Keymap, the default shortcut to open the keystrokes editor is now CTRL+Alt+Windows+K to avoid conflicts with the new global mute microphone shortcut.
|
||||||
|
* TWBlue show display properly HTML entities in tweet's text.
|
||||||
|
* TWBlue should no longer load old tweets in buffers.
|
||||||
|
* Fixed issue when uploading attachments (images, videos or gif files) while sending tweets or replies.
|
||||||
|
* Fixed an error that was making TWBlue to ask for a restart after saving account settings, even if such restart was not required. ([#413,](https://github.com/manuelcortez/TWBlue/issues/413))
|
||||||
|
|
||||||
|
## Changes in version 2021.11.12
|
||||||
|
|
||||||
|
* Now it is possible to create a tweet from a trending topics buffer again.
|
||||||
|
* TWBlue now includes a completely new set of dialogs to handle tweeting, replying and sending direct messages that takes advantage of more Twitter features.
|
||||||
|
* It is possible to add videos in tweets and direct messages by using the new "add" button, located in every dialog where media can be added. Twitter suggests to add videos from 5 seconds up to 2 minutes lenght, in mp4 format (video Codec H.264 and audio codec AAC). Currently, TWBlue does not check if the uploaded video complies with Twitter media requirements. You can add only a video in a tweet or direct message. No other kind of media can be added after a video is in a tweet. If the video was unable to be uploaded successfully, the tweet or direct message won't be created.
|
||||||
|
* Now you can add a poll to tweets. Polls can have up to 4 different options and allow voting up to 7 days after being created. Take into account, though, that currently TWBlue does not support reading polls in tweets.
|
||||||
|
* TWBlue now support threads while creating a new tweet. There is a new button, called add tweet which will add the current tweet to the thread and will allow you to write another tweet in the thread. Every tweet might include media (up to 4 photos, or one GIF image or a video) or up to one poll.
|
||||||
|
* Some functionality was removed from tweet dialogs within TWBlue. Particularly, URL shorteners and long tweets via Twishort. You still can read long tweets posted via Twishort, though.
|
||||||
|
|
||||||
|
## Changes in version 2021.11.07
|
||||||
|
|
||||||
|
* TWBlue should retrieve tweets from threads and conversations in a more reliable way. Tweets in the same thread (made by the same author) will be sorted correctly, although replies to the thread (made by different people) may not be ordered in the same way they are displayed in Twitter apps. ([#417](https://github.com/manuelcortez/TWBlue/issues/417))
|
||||||
|
* When creating a filter, TWBlue will show an error if user has not provided a name for the filter. Before, unnamed filters were a cause of config breaks in the application.
|
||||||
|
* It is again possible to read the changelog for TWBlue from the help menu in the menu bar.
|
||||||
|
* fixed a bug when clearing the direct messages buffer. ([#418](https://github.com/manuelcortez/TWBlue/issues/418))
|
||||||
|
* fixed an issue that was making TWBlue to show incorrectly titles for trending topic buffers upon startup. ([#421](https://github.com/manuelcortez/TWBlue/issues/421))
|
||||||
|
* fixed an issue that was making users of the graphical user interface to delete a buffer if a trends buffer was opened in the same session.
|
||||||
|
* Updated Spanish, Japanese and french translations.
|
||||||
|
|
||||||
|
## Changes in Version 2021.10.30
|
||||||
|
|
||||||
|
* Fixed many errors in the way we compile TWBlue, so users of 64 bits systems and particularly windows 7 users would be able to install TWBlue again. In case of issues with versions prior to 2021.10.30, please remove everything related to TWBlue (except configs) and reinstall the version 2021.10.30 to fix any possible error. This step won't be needed again in 23 months. ([#416,](https://github.com/manuelcortez/TWBlue/issues/416), [#415,](https://github.com/manuelcortez/TWBlue/issues/415))
|
||||||
|
* fixed an issue that was making impossible to manually add an user to the autocomplete users database.
|
||||||
|
* Started to improve support to conversations by searching for conversation_id.
|
||||||
|
|
||||||
|
## changes in version 2021.10.27
|
||||||
|
|
||||||
|
* Added an user alias manager, located in the application menu in the menu bar. From this dialog, it is possible to review, add, edit or remove user aliases for the current account. ([#401](https://github.com/manuelcortez/TWBlue/issues/401))
|
||||||
|
* TWBlue now closes the VLC player window automatically when a video reaches its end. ([#399](https://github.com/manuelcortez/TWBlue/issues/399))
|
||||||
|
* After a lot of time, TWBlue now uses a new default Soundpack, called FreakyBlue. This soundpack will be set by default in all new sessions created in the application. Thanks to [Andre Louis](https://twitter.com/FreakyFwoof) for the pack. ([#247](https://github.com/manuelcortez/TWBlue/issues/247))
|
||||||
|
* When reading a tweet, if the tweet contains more than 2 consecutive mentions, TWBlue will announce how many more users the tweet includes, as opposed to read every user in the conversation. You still can display the tweet to read all users.
|
||||||
|
* In the tweet displayer, It is possible to copy a link to the current tweet or person by pressing a button called "copy link to clipboard".
|
||||||
|
* Added a keymap capable to work under Windows 11. ([#391](https://github.com/manuelcortez/TWBlue/pull/391))
|
||||||
|
* Added user aliases to TWBlue. This feature allows you to rename user's display names on Twitter, so the next time you'll read an user it will be announced as you configured. For adding an alias to an user, select the "add alias" option in the user menu, located in the menu bar. This feature works only if you have set display screen names unchecked. Users are displayed with their display name in people buffers only. This action is supported in all keymaps, although it is undefined by default. ([#389](https://github.com/manuelcortez/TWBlue/pull/389))
|
||||||
|
* There are some changes to the autocomplete users feature:
|
||||||
|
* Now users can search for twitter screen names or display names in the database.
|
||||||
|
* It is possible to undefine keystrokes in the current keymap in TWBlue. This allows you, for example, to redefine keystrokes completely.
|
||||||
|
* We have changed our Geocoding service to the Nominatim API from OpenStreetMap. Addresses present in tweets are going to be determined by this service, as the Google Maps API now requires an API key. ([#390](https://github.com/manuelcortez/TWBlue/issues/390))
|
||||||
* Added a limited version of the Twitter's Streaming API: The Streaming API will work only for tweets, and will receive tweets only by people you follow. Protected users are not possible to be streamed. It is possible that during high tweet traffic, the Stream might get disconnected at times, but TWBlue should be capable of detecting this problem and reconnecting the stream again. ([#385](https://github.com/manuelcortez/TWBlue/pull/385))
|
* Added a limited version of the Twitter's Streaming API: The Streaming API will work only for tweets, and will receive tweets only by people you follow. Protected users are not possible to be streamed. It is possible that during high tweet traffic, the Stream might get disconnected at times, but TWBlue should be capable of detecting this problem and reconnecting the stream again. ([#385](https://github.com/manuelcortez/TWBlue/pull/385))
|
||||||
* Fixed an issue that made TWBlue to not show a dialog when attempting to show a profile for a suspended user. ([#387](https://github.com/manuelcortez/TWBlue/issues/387))
|
* Fixed an issue that made TWBlue to not show a dialog when attempting to show a profile for a suspended user. ([#387](https://github.com/manuelcortez/TWBlue/issues/387))
|
||||||
* Added support for Twitter audio and videos: Tweets which contains audio or videos will be detected as audio items, and you can playback those with the regular command to play audios. ([#384,](https://github.com/manuelcortez/TWBlue/pull/384))
|
* Added support for Twitter audio and videos: Tweets which contains audio or videos will be detected as audio items, and you can playback those with the regular command to play audios. ([#384,](https://github.com/manuelcortez/TWBlue/pull/384))
|
||||||
@@ -228,4 +325,4 @@
|
|||||||
* New followers and friends buffer for user timelines.
|
* New followers and friends buffer for user timelines.
|
||||||
|
|
||||||
---
|
---
|
||||||
Copyright © 2014-2017, Manuel Cortez.
|
Copyright © 2014-2021, Manuel Cortez.
|
@@ -1,28 +1,27 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from codecs import open
|
|
||||||
""" This script converts the hold documentation (saved in markdown files) in a python file with a list of strings to translate it using gettext."""
|
""" This script converts the hold documentation (saved in markdown files) in a python file with a list of strings to translate it using gettext."""
|
||||||
|
|
||||||
def prepare_documentation_in_file(fileSource, fileDest):
|
def prepare_documentation_in_file(fileSource, fileDest):
|
||||||
""" This takes documentation written in a markdown file and put all the contents in a python file, to create a translatable documentation.
|
""" This takes documentation written in a markdown file and put all the contents in a python file, to create a translatable documentation.
|
||||||
@fileSource str: A markdown(.md) file.
|
@fileSource str: A markdown(.md) file.
|
||||||
@fileDest str: A file where this will put the new strings"""
|
@fileDest str: A file where this will put the new strings"""
|
||||||
|
|
||||||
f1 = open(fileSource, "r", encoding="utf-8")
|
f1 = open(fileSource, "r", encoding="utf-8")
|
||||||
f2 = open(fileDest, "w", encoding="utf-8")
|
f2 = open(fileDest, "w", encoding="utf-8")
|
||||||
lns = f1.readlines()
|
lns = f1.readlines()
|
||||||
f2.write("# -*- coding: utf-8 -*-\n")
|
f2.write("# -*- coding: utf-8 -*-\n")
|
||||||
f2.write("documentation = [\n")
|
f2.write("documentation = [\n")
|
||||||
for i in lns:
|
for i in lns:
|
||||||
if "\n" == i:
|
if "\n" == i:
|
||||||
newvar = "\"\","
|
newvar = "\"\",\n"
|
||||||
elif "\n" == i[-1]:
|
elif "\n" == i[-1]:
|
||||||
newvar = "\"\"\"%s\"\"\",\n" % (i[:-1])
|
newvar = "_(\"\"\"%s\"\"\"),\n" % (i[:-1])
|
||||||
else:
|
else:
|
||||||
newvar = "\"\"\"%s\"\"\",\n" % (i)
|
newvar = "_(\"\"\"%s\"\"\"),\n" % (i)
|
||||||
f2.write(newvar)
|
f2.write(newvar)
|
||||||
f1.close()
|
f1.close()
|
||||||
f2.write("]")
|
f2.write("]")
|
||||||
f2.close()
|
f2.close()
|
||||||
|
|
||||||
|
|
||||||
prepare_documentation_in_file("manual.md", "strings.py")
|
prepare_documentation_in_file("manual.md", "strings.py")
|
||||||
|
120
doc/generator.py
120
doc/generator.py
@@ -5,63 +5,83 @@ import locale
|
|||||||
import paths
|
import paths
|
||||||
import markdown
|
import markdown
|
||||||
import shutil
|
import shutil
|
||||||
from codecs import open as _open
|
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
|
||||||
def get_translation_function(name, language):
|
# Languages already translated or translating the documentation.
|
||||||
if language == "en":
|
documentation_languages = ["en", "es", "fr", "de", "it", "gl", "ja", "ru", "ro", "eu", "ca", "da", "sr"]
|
||||||
return gettext.NullTranslations()
|
|
||||||
translation_function = gettext.translation(name, os.path.join(paths.app_path(), "locales"), languages=[language])
|
|
||||||
return translation_function
|
|
||||||
|
|
||||||
# the list of supported language codes of TW Blue
|
|
||||||
languages = ["en", "es", "fr", "de", "it", "gl", "ja", "ru", "ro", "eu", "ca", "da", "sr"]
|
|
||||||
|
|
||||||
def generate_document(language, document_type="documentation"):
|
# Changelog translated languages.
|
||||||
if document_type == "documentation":
|
changelog_languages = ["en", "ca", "de", "es", "eu", "fr", "gl", "ja", "ro", "ru", "sr"]
|
||||||
translation_file = "twblue-documentation"
|
|
||||||
translation_function = get_translation_function(translation_file, language)
|
# this function will help us to have both strings.py and changelog.py without issues by installing a global dummy translation function.
|
||||||
markdown_file = markdown.markdown("\n".join([translation_function.gettext(s[:-1]) if s != "\n" else s for s in strings.documentation[1:]]), extensions=["markdown.extensions.toc"])
|
def install_null_translation(name):
|
||||||
title = translation_function.gettext(strings.documentation[0][:-1])
|
_ = gettext.NullTranslations()
|
||||||
filename = "manual.html"
|
_.install()
|
||||||
elif document_type == "changelog":
|
return
|
||||||
translation_file = "twblue-changelog"
|
|
||||||
translation_function = get_translation_function(translation_file, language)
|
def get_translations(name):
|
||||||
markdown_file = markdown.markdown("\n".join([translation_function.gettext(s[:-1]) if s != "\n" else s for s in changelog.documentation[1:]]), extensions=["markdown.extensions.toc"])
|
""" Create translation instances for every language of the translated document. """
|
||||||
title = translation_function.gettext(changelog.documentation[0][:-1])
|
translations = {}
|
||||||
filename = "changelog.html"
|
if "documentation" in name:
|
||||||
first_html_block = """<!doctype html>
|
langs = documentation_languages
|
||||||
<html lang="%s">
|
else:
|
||||||
<head>
|
langs = changelog_languages
|
||||||
<title>%s</title>
|
for l in langs:
|
||||||
<meta charset="utf-8">
|
if l != "en":
|
||||||
</head>
|
_ = gettext.translation(name, os.path.join(paths.app_path(), "locales"), languages=[l])
|
||||||
<body>
|
translations[l] = _
|
||||||
<header><h1>%s</h1></header>
|
else:
|
||||||
""" % (language, title, title)
|
_ = gettext.NullTranslations()
|
||||||
first_html_block = first_html_block+ markdown_file
|
translations[l] = _
|
||||||
first_html_block = first_html_block + "\n</body>\n</html>"
|
return translations
|
||||||
if not os.path.exists(os.path.join("documentation", language)):
|
|
||||||
os.mkdir(os.path.join("documentation", language))
|
def generate_document(lang, lang_name, document_type="documentation"):
|
||||||
mdfile = _open(os.path.join("documentation", language, filename), "w", encoding="utf-8")
|
""" Generates a document by using the provided lang object, which should be a translation, and lang_name, which should be the two letter code representing the language. """
|
||||||
mdfile.write(first_html_block)
|
if document_type == "documentation":
|
||||||
mdfile.close()
|
translation_file = "twblue-documentation"
|
||||||
|
markdown_file = markdown.markdown("\n".join([lang.gettext(s) if s != "" else s for s in strings.documentation[1:]]), extensions=["markdown.extensions.toc"])
|
||||||
|
title = lang.gettext(strings.documentation[0])
|
||||||
|
filename = "manual.html"
|
||||||
|
elif document_type == "changelog":
|
||||||
|
translation_file = "twblue-changelog"
|
||||||
|
markdown_file = markdown.markdown("\n".join([lang.gettext(s) if s != "" else s for s in changelog.documentation[1:]]), extensions=["markdown.extensions.toc"])
|
||||||
|
title = lang.gettext(changelog.documentation[0])
|
||||||
|
filename = "changelog.html"
|
||||||
|
first_html_block = """<!doctype html>
|
||||||
|
<html lang="%s">
|
||||||
|
<head>
|
||||||
|
<title>%s</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header><h1>%s</h1></header>
|
||||||
|
""" % (lang_name, title, title)
|
||||||
|
first_html_block = first_html_block+ markdown_file
|
||||||
|
first_html_block = first_html_block + "\n</body>\n</html>"
|
||||||
|
if not os.path.exists(os.path.join("documentation", lang_name)):
|
||||||
|
os.mkdir(os.path.join("documentation", lang_name))
|
||||||
|
mdfile = open(os.path.join("documentation", lang_name, filename), "w", encoding="utf-8")
|
||||||
|
mdfile.write(first_html_block)
|
||||||
|
mdfile.close()
|
||||||
|
|
||||||
def create_documentation():
|
def create_documentation():
|
||||||
print("Creating documentation in the supported languages...\n")
|
changelog_translations = get_translations("twblue-changelog")
|
||||||
if not os.path.exists("documentation"):
|
documentation_translations = get_translations("twblue-documentation")
|
||||||
os.mkdir("documentation")
|
print("Creating documentation in the supported languages...\n")
|
||||||
if os.path.exists(os.path.join("documentation", "license.txt")) == False:
|
if not os.path.exists("documentation"):
|
||||||
shutil.copy(os.path.join("..", "license.txt"), os.path.join("documentation", "license.txt"))
|
os.mkdir("documentation")
|
||||||
for i in languages:
|
if os.path.exists(os.path.join("documentation", "license.txt")) == False:
|
||||||
print("Creating documentation for: %s" % (i,))
|
shutil.copy(os.path.join("..", "license.txt"), os.path.join("documentation", "license.txt"))
|
||||||
try:
|
for i in documentation_languages:
|
||||||
generate_document(i)
|
print("Creating documentation for: %s" % (i,))
|
||||||
generate_document(i, "changelog")
|
generate_document(lang_name=i, lang=documentation_translations.get(i))
|
||||||
except:
|
for i in changelog_languages:
|
||||||
continue
|
print("Creating changelog for: %s" % (i,))
|
||||||
print("Done")
|
generate_document(lang_name=i, lang=changelog_translations.get(i), document_type="changelog")
|
||||||
|
print("Done")
|
||||||
|
|
||||||
|
install_null_translation("twblue-documentation")
|
||||||
import strings
|
import strings
|
||||||
import changelog
|
import changelog
|
||||||
create_documentation()
|
create_documentation()
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-07 13:48-0500\n"
|
"PO-Revision-Date: 2018-08-07 13:48-0500\n"
|
||||||
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2015-11-27 08:32-0600\n"
|
"PO-Revision-Date: 2015-11-27 08:32-0600\n"
|
||||||
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: Mohammed Al Shara <mohammed@atexplorer.com>\n"
|
"Language-Team: Mohammed Al Shara <mohammed@atexplorer.com>\n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TWBlue-Changelog V0.93\n"
|
"Project-Id-Version: TWBlue-Changelog V0.93\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-08 11:46+0200\n"
|
"PO-Revision-Date: 2018-08-08 11:46+0200\n"
|
||||||
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: Fran Torres Gallego. <frantorresgallego@gmail.com>\n"
|
"Language-Team: Fran Torres Gallego. <frantorresgallego@gmail.com>\n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.89\n"
|
"Project-Id-Version: TW Blue documentation 0.89\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2017-03-25 15:15+0100\n"
|
"PO-Revision-Date: 2017-03-25 15:15+0100\n"
|
||||||
"Last-Translator: Joan Rabat <joanrabat@hotmail.com>\n"
|
"Last-Translator: Joan Rabat <joanrabat@hotmail.com>\n"
|
||||||
"Language-Team: Francisco Torres Gallego <frantorresgallego@gmail.com>\n"
|
"Language-Team: Francisco Torres Gallego <frantorresgallego@gmail.com>\n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-11-17 10:25+0100\n"
|
"PO-Revision-Date: 2018-11-17 10:25+0100\n"
|
||||||
"Last-Translator: Nicolai Svendsen <chojiro1990@gmail.com>\n"
|
"Last-Translator: Nicolai Svendsen <chojiro1990@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
BIN
doc/locales/de/LC_MESSAGES/twblue-changelog.mo
Normal file
BIN
doc/locales/de/LC_MESSAGES/twblue-changelog.mo
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2019-03-17 16:39+0100\n"
|
"PO-Revision-Date: 2019-03-17 16:39+0100\n"
|
||||||
"Last-Translator: Steffen Schultz <steffenschultz@mailbox.org>\n"
|
"Last-Translator: Steffen Schultz <steffenschultz@mailbox.org>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
BIN
doc/locales/de/LC_MESSAGES/twblue-documentation.mo
Normal file
BIN
doc/locales/de/LC_MESSAGES/twblue-documentation.mo
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TWBlue Documentation\n"
|
"Project-Id-Version: TWBlue Documentation\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-08 11:01+0200\n"
|
"PO-Revision-Date: 2018-08-08 11:01+0200\n"
|
||||||
"Last-Translator: Steffen Schultz <schulle3o@yahoo.de>\n"
|
"Last-Translator: Steffen Schultz <schulle3o@yahoo.de>\n"
|
||||||
"Language-Team: Steffen Schultz <schulle3o@yahoo.de>\n"
|
"Language-Team: Steffen Schultz <schulle3o@yahoo.de>\n"
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: twblue-documentation 0.84\n"
|
"Project-Id-Version: twblue-documentation 0.84\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2019-05-06 23:06+0200\n"
|
"PO-Revision-Date: 2019-05-06 23:06+0200\n"
|
||||||
"Last-Translator: José Manuel Delicado <jmdaweb@hotmail.com>\n"
|
"Last-Translator: José Manuel Delicado <jmdaweb@hotmail.com>\n"
|
||||||
"Language-Team: Spanish <manuel@manuelcortez.net>\n"
|
"Language-Team: Spanish <manuel@manuelcortez.net>\n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-07 13:51-0500\n"
|
"PO-Revision-Date: 2018-08-07 13:51-0500\n"
|
||||||
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
@@ -1,635 +0,0 @@
|
|||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR ORGANIZATION
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: \n"
|
|
||||||
"POT-Creation-Date: 2017-07-08 16:25+Hora de verano central (Mxico)\n"
|
|
||||||
"PO-Revision-Date: 2017-07-15 19:44+0200\n"
|
|
||||||
"Last-Translator: Sukil Etxenike <sukiletxe@yahoo.es>\n"
|
|
||||||
"Language-Team: \n"
|
|
||||||
"Language: eu\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Generated-By: pygettext.py 1.5\n"
|
|
||||||
"X-Generator: Poedit 2.0.1\n"
|
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:3
|
|
||||||
msgid "TWBlue Changelog"
|
|
||||||
msgstr "TwBlueren aldaketak"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:4
|
|
||||||
msgid "## changes in this version"
|
|
||||||
msgstr "## Aldaketak bertsio honetan"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:5
|
|
||||||
msgid ""
|
|
||||||
"* TWBlue will show an error when trying to open a timeline for a suspended "
|
|
||||||
"user. ([#128](https://github.com/manuelcortez/TWBlue/issues/128))"
|
|
||||||
msgstr ""
|
|
||||||
"* TWBluek errore bat erakutsiko du ezabatutako erabiltzaile batn denbora "
|
|
||||||
"lerro bat irekitzen saiatzean . ([#128](https://github.com/manuelcortez/"
|
|
||||||
"TWBlue/issues/128))"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:6
|
|
||||||
msgid ""
|
|
||||||
"* Removed TwUp as service as it no longer exists. ([#112](https://github.com/"
|
|
||||||
"manuelcortez/TWBlue/issues/112))"
|
|
||||||
msgstr ""
|
|
||||||
"* TwUp zerbitzua kendu da, jada ez delako existitzen. ([#112](https://github."
|
|
||||||
"com/manuelcortez/TWBlue/issues/112)) "
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:7
|
|
||||||
msgid ""
|
|
||||||
"* Release audio files after uploading them. ([#130](https://github.com/"
|
|
||||||
"manuelcortez/TWBlue/issues/130))"
|
|
||||||
msgstr ""
|
|
||||||
"* Orain audio fitxategiak askatzen dira igo ondoren. ([#130](https://github."
|
|
||||||
"com/manuelcortez/TWBlue/issues/130))"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:8
|
|
||||||
msgid ""
|
|
||||||
"* Now TWBlue will use Yandex's translation services instead microsoft "
|
|
||||||
"translator. ([#132](https://github.com/manuelcortez/TWBlue/issues/132))"
|
|
||||||
msgstr ""
|
|
||||||
"* Orain TWBluek Yandexen itzultzailea erabiltzen du Microsoften "
|
|
||||||
"itzultzailearen ordez. ([#132](https://github.com/manuelcortez/TWBlue/"
|
|
||||||
"issues/132))"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:9
|
|
||||||
msgid ""
|
|
||||||
"* SndUp users will be able to upload audio in their account by using their "
|
|
||||||
"API Key again. ([#134](https://github.com/manuelcortez/TWBlue/issues/134))"
|
|
||||||
msgstr ""
|
|
||||||
"* SndUp-en erabiltzaileek orain audioak igo ditzakete haien API kodea "
|
|
||||||
"erabilita. ([#134](https://github.com/manuelcortez/TWBlue/issues/134))"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:10
|
|
||||||
msgid ""
|
|
||||||
"* old tweets shouldn't be added as new items in buffers. ([#116,](https://"
|
|
||||||
"github.com/manuelcortez/TWBlue/issues/116)) ([#133](https://github.com/"
|
|
||||||
"manuelcortez/TWBlue/issues/133))"
|
|
||||||
msgstr ""
|
|
||||||
"* Txio zaharrak ez lirateke buferretan elementu berri gisa agertu behar. "
|
|
||||||
"([#116,](https://github.com/manuelcortez/TWBlue/issues/116)) ([#133](https://"
|
|
||||||
"github.com/manuelcortez/TWBlue/issues/133))"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:11
|
|
||||||
msgid ""
|
|
||||||
"* All mentionned users should be displayed correctly in Twishort's long "
|
|
||||||
"tweets. ([#116,](https://github.com/manuelcortez/TWBlue/issues/116)) ([#135]"
|
|
||||||
"(https://github.com/manuelcortez/TWBlue/issues/135))"
|
|
||||||
msgstr ""
|
|
||||||
"* Aipatutako erabiltzaile guztiak ondo agertu beharko lirateke Tuishort-en "
|
|
||||||
"txio luzeetan. ([#116,](https://github.com/manuelcortez/TWBlue/issues/116)) "
|
|
||||||
"([#135](https://github.com/manuelcortez/TWBlue/issues/135))"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:12
|
|
||||||
msgid ""
|
|
||||||
"* It is possible to select a language for OCR service from the extras panel, "
|
|
||||||
"in the account settings dialogue. You can, however, set this to detect "
|
|
||||||
"automatically. OCR should work better in languages with special characters "
|
|
||||||
"or non-english symbols. ([#107](https://github.com/manuelcortez/TWBlue/"
|
|
||||||
"issues/107))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:13
|
|
||||||
msgid ""
|
|
||||||
"* Fixed a problem with JAWS for Windows and TWBlue. Now JAWS will work "
|
|
||||||
"normally in this update. [#100](https://github.com/manuelcortez/twblue/"
|
|
||||||
"issues/100)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:14
|
|
||||||
msgid "* And more ([#136,](https://github.com/manuelcortez/TWBlue/issues/136))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:15
|
|
||||||
msgid "## Changes in version 0.90"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:16
|
|
||||||
msgid ""
|
|
||||||
"* Fixed a bug in long tweet parsing that was making TWBlue to disconnect the "
|
|
||||||
"streaming API. ([#103](https://github.com/manuelcortez/TWBlue/issues/103))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:17
|
|
||||||
msgid ""
|
|
||||||
"* Now OCR will work in images from retweets. It fixes a bug where TWBlue was "
|
|
||||||
"detecting images but couldn't apply OCR on them. ([#105](https://github.com/"
|
|
||||||
"manuelcortez/TWBlue/issues/105))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:18
|
|
||||||
msgid ""
|
|
||||||
"* TWBlue won't try to load tweets already deleted, made with Twishort. "
|
|
||||||
"Before, if someone posted a long tweet but deleted it in the Twishort's "
|
|
||||||
"site, TWBlue was trying to load the tweet and it was causing problems in all "
|
|
||||||
"the client. ([#113](https://github.com/manuelcortez/TWBlue/issues/113))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:19
|
|
||||||
msgid ""
|
|
||||||
"* TWBlue shows an error message when you try to view the profile of an user "
|
|
||||||
"that does not exist or has been suspended. ([#114,](https://github.com/"
|
|
||||||
"manuelcortez/TWBlue/issues/114) [#115](https://github.com/manuelcortez/"
|
|
||||||
"TWBlue/issues/115))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:20
|
|
||||||
msgid ""
|
|
||||||
"* The spellchecker module should select the right language when is set to "
|
|
||||||
"\"user default\". ([#117](https://github.com/manuelcortez/TWBlue/issues/117))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:21
|
|
||||||
msgid ""
|
|
||||||
"* Image description will be displayed in retweets too. ([#119](https://"
|
|
||||||
"github.com/manuelcortez/TWBlue/issues/119))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:22
|
|
||||||
msgid ""
|
|
||||||
"* When reading a long tweet, you shouldn't read strange entities anymore. "
|
|
||||||
"([#118](https://github.com/manuelcortez/twblue/issues/118))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:23
|
|
||||||
msgid ""
|
|
||||||
"* TWBlue will not try to load timelines if the user is blocking you. ([#125]"
|
|
||||||
"(https://github.com/manuelcortez/twblue/issues/125))"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:24
|
|
||||||
msgid "## Changes in version 0.88 and 0.89"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:25
|
|
||||||
msgid "* Fixed more issues with streams and reconnections."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:26
|
|
||||||
msgid "* newer updates will indicate the release date in the updater."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:27
|
|
||||||
msgid ""
|
|
||||||
"* Changes to keystrokes are reflected in keystroke editor automatically."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:28
|
|
||||||
msgid ""
|
|
||||||
"* In replies with multiple users, if the mention to all checkbox is "
|
|
||||||
"unchecked, you will see a checkbox per user so you will be able to control "
|
|
||||||
"who will be mentioned in the reply."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:29
|
|
||||||
msgid ""
|
|
||||||
"* Fixed a bug that caused duplicated user mentions in replies when the tweet "
|
|
||||||
"was made with Twishort."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:30
|
|
||||||
msgid ""
|
|
||||||
"* Retweets should be displayed normally again when the originating tweet is "
|
|
||||||
"a Twishort's long tweet."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:31
|
|
||||||
msgid ""
|
|
||||||
"* Changed the way TWBlue saves user timelines in configuration. Now it uses "
|
|
||||||
"user IDS instead usernames. With user IDS, if an user changes the username, "
|
|
||||||
"TWBlue still will create his/her timeline. This was not possible by using "
|
|
||||||
"usernames."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:32
|
|
||||||
msgid ""
|
|
||||||
"* Added a new setting in the account settings dialogue that makes TWBlue to "
|
|
||||||
"show twitter usernames instead the full name."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:33
|
|
||||||
msgid ""
|
|
||||||
"* Added OCR in twitter pictures. There is a new item in the tweet menu that "
|
|
||||||
"allows you to extract and display text in images. Also the keystroke alt+Win"
|
|
||||||
"+o has been added for the same purpose from the invisible interface."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:34
|
|
||||||
msgid "* Now TWBlue will play a sound when the focused tweet contains images."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:35
|
|
||||||
msgid ""
|
|
||||||
"* Your own quoted tweets will not appear in the mentions buffer anymore."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:36
|
|
||||||
msgid ""
|
|
||||||
"* The config file is saved in a different way, it should fix the bug where "
|
|
||||||
"TWBlue needs to be restarted after the config folder is deleted."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:37
|
|
||||||
msgid "* Mentioning people from friends or followers buffers works again."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:38
|
|
||||||
msgid ""
|
|
||||||
"* Support for proxy servers has been improved. Now TWBlue supports http, "
|
|
||||||
"https, socks4 and socks5 proxies, with and without autentication."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:39
|
|
||||||
msgid "## Changes in version 0.87"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:40
|
|
||||||
msgid "* Fixed stream connection errors."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:41
|
|
||||||
msgid ""
|
|
||||||
"* Now TWBlue can handle properly a reply to the sender without including all "
|
|
||||||
"other mentioned users."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:42
|
|
||||||
msgid "* Updated translations."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:43
|
|
||||||
msgid ""
|
|
||||||
"* The status of the mention to all checkbox will be remembered the next time "
|
|
||||||
"you reply to multiple users."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:44
|
|
||||||
msgid "## Changes in version 0.86"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:45
|
|
||||||
msgid ""
|
|
||||||
"* Fixed a very important security issue. Now TWBlue will send tweets to "
|
|
||||||
"twishort without using any other server."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:46
|
|
||||||
msgid ""
|
|
||||||
"* When you add a comment to a tweet, it will be sent as a quoted tweet, even "
|
|
||||||
"if your reply plus the original tweet is not exceeding 140 characters."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:47
|
|
||||||
msgid ""
|
|
||||||
"* Updated windows 10 keymap for reflecting changes made in the last windows "
|
|
||||||
"10 build."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:48
|
|
||||||
msgid "* Added last changes in the twitter API."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:49
|
|
||||||
msgid ""
|
|
||||||
"* When replying, it will not show the twitter username in the text box. When "
|
|
||||||
"you send the tweet, the username will be added automatically."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:50
|
|
||||||
msgid ""
|
|
||||||
"* When replying to multiple users, you'll have a checkbox instead a button "
|
|
||||||
"for mentioning all people. If this is checked, twitter usernames will be "
|
|
||||||
"added automatically when you send your reply."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:51
|
|
||||||
msgid "## Changes in version 0.85"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:52
|
|
||||||
msgid "* Long and quoted tweets should be displayed properly In lists."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:53
|
|
||||||
msgid "* The connection should be more stable."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:54
|
|
||||||
msgid "* Added an autostart option in the global settings dialogue."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:55
|
|
||||||
msgid "* Updated translation."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:56
|
|
||||||
msgid "* Updated russian documentation."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:57
|
|
||||||
msgid "* Tweets in cached database should be loaded properly."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:58
|
|
||||||
msgid "* Added some missed dictionaries for spelling correction."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:59
|
|
||||||
msgid ""
|
|
||||||
"* Timelines, lists and other buffer should be created in the right order at "
|
|
||||||
"startup."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:60
|
|
||||||
msgid "## Changes in version 0.84 "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:61
|
|
||||||
msgid "* More improvements in quoted and long tweets."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:62
|
|
||||||
msgid ""
|
|
||||||
"* Updated translations: Russian, Italian, French, Romanian, Galician and "
|
|
||||||
"Finnish."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:63
|
|
||||||
msgid ""
|
|
||||||
"* Improvements in the audio uploader module: Now it can handle audio with "
|
|
||||||
"non-english characters."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:64
|
|
||||||
msgid ""
|
|
||||||
"* the title of the window should be updated properly when spellcheck, "
|
|
||||||
"translate or shorten/unshorten URL buttons are pressed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:65
|
|
||||||
msgid ""
|
|
||||||
"* the bug that changes the selected tweet in the home timeline shouldn't be "
|
|
||||||
"happening so often."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:66
|
|
||||||
msgid "## Changes in version 0.82 and 0.83"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:67
|
|
||||||
msgid ""
|
|
||||||
"* If the tweet source (client) is an application with unicode characters "
|
|
||||||
"(example: российская газета) it will not break the tweet displayer."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:68
|
|
||||||
msgid ""
|
|
||||||
"* Added a new field for image description in tweet displayer. When "
|
|
||||||
"available, it will show description for images posted in tweets."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:69
|
|
||||||
msgid ""
|
|
||||||
"* users can add image descriptions to their photos. When uploading an image, "
|
|
||||||
"a dialog will show for asking a description."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:70
|
|
||||||
msgid "* Redesigned upload image dialog."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:71
|
|
||||||
msgid "* Fixed photo uploads when posting tweets."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:72
|
|
||||||
msgid ""
|
|
||||||
"* When getting tweets for a conversation, ignores deleted tweets or some "
|
|
||||||
"errors, now TWBlue will try to get as much tweets as possible, even if some "
|
|
||||||
"of these are no longer available."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:73
|
|
||||||
msgid "* Added audio playback from soundcloud."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:74
|
|
||||||
msgid "* Now the session mute option don't makes the screen reader speaks."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:75
|
|
||||||
msgid "* Fixed the direct message dialog. Now it should be displayed properly."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:76
|
|
||||||
msgid ""
|
|
||||||
"* when a tweet is deleted in twitter, TWBlue should reflect this change and "
|
|
||||||
"delete that tweet in every buffer it is displayed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:77
|
|
||||||
msgid ""
|
|
||||||
"* If your session is broken, TWBlue will be able to remove it automatically "
|
|
||||||
"instead just crashing."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:78
|
|
||||||
msgid "* audio uploader should display the current progress."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:79
|
|
||||||
msgid ""
|
|
||||||
"* users can disable the check for updates feature at startup from the "
|
|
||||||
"general tab, in the global settings dialogue."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:80
|
|
||||||
msgid ""
|
|
||||||
"* The invisible interface and the window should be synchronized when the "
|
|
||||||
"client reconnects."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:81
|
|
||||||
msgid "* The documentation option in the systray icon should be enabled."
|
|
||||||
msgstr ""
|
|
||||||
"* Sistemaren ikonoetako dokumentazioa ikusteko aukera erabilgarria egon "
|
|
||||||
"beharko litzateke."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:82
|
|
||||||
msgid ""
|
|
||||||
"* In trending buffers, you can press enter for posting a tweet about the "
|
|
||||||
"focused trend."
|
|
||||||
msgstr ""
|
|
||||||
"* Tendentzien buferretan, enter saka dezakezu enfokatutako tendentziari "
|
|
||||||
"buruz txio bat argitaratzeko."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:83
|
|
||||||
msgid ""
|
|
||||||
"* Updated russian documentation and main program interface (thanks to "
|
|
||||||
"Natalia Hedlund (Наталья Хедлунд), [@lifestar_n](https://twitter.com/"
|
|
||||||
"lifestar_n) in twitter)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:84
|
|
||||||
msgid "* updated translations."
|
|
||||||
msgstr "* Itzulpenak eguneratuak izan dira."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:85
|
|
||||||
msgid "## Changes in Version 0.81"
|
|
||||||
msgstr "## 0.81bertsioaren aldaketak"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:86
|
|
||||||
msgid "* Updated translations"
|
|
||||||
msgstr "* Itzulpenak eguneratuak izan dira"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:87
|
|
||||||
msgid ""
|
|
||||||
"* The updater module has received some improvements. Now it includes a "
|
|
||||||
"Mirror URL for checking updates if the main URL is not available at the "
|
|
||||||
"moment. If something is wrong and both locations don't work, the program "
|
|
||||||
"will start anyway."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:88
|
|
||||||
msgid "* some GUI elements now use keyboard shortcuts for common actions."
|
|
||||||
msgstr ""
|
|
||||||
"* Interfaze grafikoko elementu batzuek lasterbide teklak dituzte ohiko "
|
|
||||||
"ekintzetarako."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:89
|
|
||||||
msgid "* fixed a bug in the geolocation dialog."
|
|
||||||
msgstr "* Errore bat konpondu da geottxioen elkarrizketa-koadroan."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:90
|
|
||||||
msgid "* the chicken nugget keymap should work properly."
|
|
||||||
msgstr "* Chicken Nuggetaren teklatu-mapak ondo funtzionatu beharko luke."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:91
|
|
||||||
msgid ""
|
|
||||||
"* Added a new soundpack to the default installation of TWBlue, thanks to "
|
|
||||||
"[@Deng90](https://twitter.com/deng90)"
|
|
||||||
msgstr ""
|
|
||||||
"* Soinu pakete berri bat gehitu zaio TWBlueren lehenetsitako instalazioari, "
|
|
||||||
"eskerrak [@Deng90](https://twitter.com/deng90)"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:92
|
|
||||||
msgid "* Now the changelog is written in an html File."
|
|
||||||
msgstr "* Orain aldaketen fitxategia html fitxategi bat da."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:93
|
|
||||||
msgid ""
|
|
||||||
"* Added some missed dictionaries in last version for the spell checking "
|
|
||||||
"feature."
|
|
||||||
msgstr ""
|
|
||||||
"* Aurreko bertsioan falta ziren hiztegi batzuk gehitu dira, zuzentzaleak "
|
|
||||||
"erabiltzen dituenak."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:94
|
|
||||||
msgid ""
|
|
||||||
"* Trimmed the beginnings of the sounds in the default soundpack. Thanks to "
|
|
||||||
"[@masonasons](https://github.com/masonasons)"
|
|
||||||
msgstr ""
|
|
||||||
"* ehenetsitako soiinu paketearen soinuen hasierak moztu dira. Eskerrak "
|
|
||||||
"[@masonasons-i.](https://github.com/masonasons)"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:95
|
|
||||||
msgid ""
|
|
||||||
"* Added Opus support for sound playback in TWBlue. Thanks to [@masonasons]"
|
|
||||||
"(https://github.com/masonasons)"
|
|
||||||
msgstr ""
|
|
||||||
"* Opus formatua erreproduzi daiteke, eskerrak [@masonasons-i.](https://"
|
|
||||||
"github.com/masonasons)."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:96
|
|
||||||
msgid ""
|
|
||||||
"* Added a source field in view tweet dialogue. Thanks to [@masonasons]"
|
|
||||||
"(https://github.com/masonasons)"
|
|
||||||
msgstr ""
|
|
||||||
"* \"Iturria\" gehitu zaio txioa erakusteko elkarrizketa koadroari. Eskerrak "
|
|
||||||
"[@masonasons-i.](https://github.com/masonasons)"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:97
|
|
||||||
msgid ""
|
|
||||||
"* You can load previous items in followers and friend buffers for others."
|
|
||||||
msgstr ""
|
|
||||||
"* Aurreko elementuak karga ditzakezu besteen jarraitzaile eta lagunen "
|
|
||||||
"buferretan."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:98
|
|
||||||
msgid ""
|
|
||||||
"* The Spell Checker dialogue should not display an error message when you "
|
|
||||||
"have set \"default language\" in the global settings dialogue if your "
|
|
||||||
"language is supported [#168](http://twblue.es/bugs/view.php?id=168)"
|
|
||||||
msgstr ""
|
|
||||||
"* Zuzentzailearen elkarrizketa-koadroak ez luke errorerik erakutsi behar "
|
|
||||||
"aukera globaletan \"Lehenetsitako hizkuntza\" aukeratua dagoenean eta zure "
|
|
||||||
"hizkuntza erabilgarria denean [#168](http://twblue.es/bugs/view.php?id=168)"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:99
|
|
||||||
msgid "* Updated romanian translation."
|
|
||||||
msgstr "* Errumaniera itzulpena eguneratua izan da."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:100
|
|
||||||
msgid "* Some code cleanups."
|
|
||||||
msgstr "* Kode garbiketa batzuk."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:101
|
|
||||||
msgid "* The bug reports feature is fully operational again."
|
|
||||||
msgstr "* Arazoez informatzeko ezaugarriak berriz funtzionaten du"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:102
|
|
||||||
msgid ""
|
|
||||||
"* TWBlue should work again for users that contains special characters in "
|
|
||||||
"windows usernames."
|
|
||||||
msgstr ""
|
|
||||||
"* TWBluek berriz funtzionatu beharko luke haien Windows erabiltzaile-"
|
|
||||||
"izenetan karaktere bereziak dituzten erabiltzaileentzat."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:103
|
|
||||||
msgid "* Added more options for the tweet searches."
|
|
||||||
msgstr "* Txioen bilaketarako aukera gehiago gehitu dira."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:104
|
|
||||||
msgid "* Added play_audio to the keymap editor."
|
|
||||||
msgstr "* play_audio teklatu-mapen editorera gehitua izan da."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:105
|
|
||||||
msgid "* Windows key is no longer required in the keymap editor"
|
|
||||||
msgstr "* Windows tekla ez da jada bearrezkoa teklatu-mapen editorean."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:106
|
|
||||||
msgid "* Switched to the Microsoft translator."
|
|
||||||
msgstr "* Microsoften itzultzailera aldatu gara."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:107
|
|
||||||
msgid ""
|
|
||||||
"* You can update the current buffer by pressing ctrl+win+shift+u in the "
|
|
||||||
"default keymap or in the buffer menu."
|
|
||||||
msgstr ""
|
|
||||||
"* Enfokatutako uferra ktrl+shift+win+u sakatuta (lehenetsitako teklatu-"
|
|
||||||
"mapak) edo menuan eguneratu daitezke."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:108
|
|
||||||
msgid "* Changed some keystrokes in the windows 10 default keymap"
|
|
||||||
msgstr ""
|
|
||||||
"* Lasterbide-tekla batzuk aldatuak izan dira Windows 10erako teklatu-mapan."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:109
|
|
||||||
msgid "* New followers and friends buffer for user timelines."
|
|
||||||
msgstr ""
|
|
||||||
"* Jarraitzaileen eta lagunen bufer berria erabiltzaileen denbora-lerroentzat."
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:110
|
|
||||||
msgid "---"
|
|
||||||
msgstr "---"
|
|
||||||
|
|
||||||
#: ../doc/changelog.py:111
|
|
||||||
msgid "Copyright © 2014-2017, Manuel Cortez."
|
|
||||||
msgstr "Copyright © 2014-2017, Manuel Cortez."
|
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2015-11-27 08:33-0600\n"
|
"PO-Revision-Date: 2015-11-27 08:33-0600\n"
|
||||||
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: Sukil Echenique <sukiletxe@yahoo.es>\n"
|
"Language-Team: Sukil Echenique <sukiletxe@yahoo.es>\n"
|
||||||
|
BIN
doc/locales/fi/lc_messages/twblue-changelog.mo
Normal file
BIN
doc/locales/fi/lc_messages/twblue-changelog.mo
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-07 13:52-0500\n"
|
"PO-Revision-Date: 2018-08-07 13:52-0500\n"
|
||||||
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortez <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
BIN
doc/locales/fi/lc_messages/twblue-documentation.mo
Normal file
BIN
doc/locales/fi/lc_messages/twblue-documentation.mo
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-27 16:37+0200\n"
|
"PO-Revision-Date: 2018-08-27 16:37+0200\n"
|
||||||
"Last-Translator: Jani Kinnunen <jani.kinnunen@wippies.fi>\n"
|
"Last-Translator: Jani Kinnunen <jani.kinnunen@wippies.fi>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: twblue-changelog 0.93\n"
|
"Project-Id-Version: twblue-changelog 0.93\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estándar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2019-07-22 16:16+0200\n"
|
"PO-Revision-Date: 2019-07-22 16:16+0200\n"
|
||||||
"Last-Translator: Corentin BACQUÉ-CAZENAVE <corentin@progaccess33.net>\n"
|
"Last-Translator: Corentin BACQUÉ-CAZENAVE <corentin@progaccess33.net>\n"
|
||||||
"Language-Team: Corentin BACQUÉ-CAZENAVE <corentin@progaccess.net>\n"
|
"Language-Team: Corentin BACQUÉ-CAZENAVE <corentin@progaccess.net>\n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.88\n"
|
"Project-Id-Version: TW Blue documentation 0.88\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-11 12:25+0200\n"
|
"PO-Revision-Date: 2018-08-11 12:25+0200\n"
|
||||||
"Last-Translator: Rémy Ruiz <remyruiz@gmail.com>\n"
|
"Last-Translator: Rémy Ruiz <remyruiz@gmail.com>\n"
|
||||||
"Language-Team: Rémy Ruiz <remyruiz@gmail.com>\n"
|
"Language-Team: Rémy Ruiz <remyruiz@gmail.com>\n"
|
||||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2019-05-12 22:19+0100\n"
|
"PO-Revision-Date: 2019-05-12 22:19+0100\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: tw blue documentation 0.46\n"
|
"Project-Id-Version: tw blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-08 11:34+0100\n"
|
"PO-Revision-Date: 2018-08-08 11:34+0100\n"
|
||||||
"Last-Translator: Juan C. Buño <oprisniki@gmail.com>\n"
|
"Last-Translator: Juan C. Buño <oprisniki@gmail.com>\n"
|
||||||
"Language-Team: Alba Quinteiro <alba_080695@hotmail.com>\n"
|
"Language-Team: Alba Quinteiro <alba_080695@hotmail.com>\n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2017-12-11 11:07-0600\n"
|
"PO-Revision-Date: 2017-12-11 11:07-0600\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2015-11-27 08:34-0600\n"
|
"PO-Revision-Date: 2015-11-27 08:34-0600\n"
|
||||||
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2017-12-11 11:07-0600\n"
|
"PO-Revision-Date: 2017-12-11 11:07-0600\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-09 11:51+0100\n"
|
"PO-Revision-Date: 2018-08-09 11:51+0100\n"
|
||||||
"Last-Translator: Chris Leo Mameli <llajta2012@gmail.com>\n"
|
"Last-Translator: Chris Leo Mameli <llajta2012@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-08 19:52+0900\n"
|
"PO-Revision-Date: 2018-08-08 19:52+0900\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-08 19:09+0900\n"
|
"PO-Revision-Date: 2018-08-08 19:09+0900\n"
|
||||||
"Last-Translator: Masamitsu Misono <misono@nvsupport.org>\n"
|
"Last-Translator: Masamitsu Misono <misono@nvsupport.org>\n"
|
||||||
"Language-Team: NVDA Help Desk <nvdahelp@center-aikoh.net>\n"
|
"Language-Team: NVDA Help Desk <nvdahelp@center-aikoh.net>\n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2017-12-11 11:08-0600\n"
|
"PO-Revision-Date: 2017-12-11 11:08-0600\n"
|
||||||
"Last-Translator: zvonimir stanecic <zvonimirek222@yandex.com>\n"
|
"Last-Translator: zvonimir stanecic <zvonimirek222@yandex.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2017-01-22 21:42+0100\n"
|
"PO-Revision-Date: 2017-01-22 21:42+0100\n"
|
||||||
"Last-Translator: Zvonimir Stanečić <zvonimirek222@yandex.com>\n"
|
"Last-Translator: Zvonimir Stanečić <zvonimirek222@yandex.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2017-12-11 11:08-0600\n"
|
"PO-Revision-Date: 2017-12-11 11:08-0600\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2015-11-27 08:35-0600\n"
|
"PO-Revision-Date: 2015-11-27 08:35-0600\n"
|
||||||
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
@@ -1,285 +0,0 @@
|
|||||||
% Documentação do TW Blue 0.42
|
|
||||||
|
|
||||||
# Versão 0.42 (alpha)
|
|
||||||
|
|
||||||
# ¡Perigro!
|
|
||||||
|
|
||||||
Você está lendo um documento gerado para uma aplicação em fase de desenvolvimento. A intenção deste manual é esclarecer alguns detalhes sobre o funcionamento do programa. Note-se que sendo desenvolvido ativamente, o software pode mudar um pouco em relação a esta documentação num futuro próximo. Por isso é aconselhável dar uma olhada de vez em quando para não se perder muito.
|
|
||||||
|
|
||||||
Si quieres ver lo que ha cambiado con respecto a la versión anterior, [lee la lista de novedades aquí.](changes.html)
|
|
||||||
|
|
||||||
# TW Blue
|
|
||||||
|
|
||||||
TW Blue é um aplicativo para utilizar o Twitter de forma simples e rápida, além de evitar tanto quanto possível consumir demasiados recursos do computador. Com ele é possível realizar ações do Twitter, tais como:
|
|
||||||
|
|
||||||
* Crear, responder, reenviar y eliminar Tuits,
|
|
||||||
* Marcar como favorito, eliminar de tus favoritos un tuit,
|
|
||||||
* Enviar y eliminar mensajes directos,
|
|
||||||
* Ver tus amigos y seguidores,
|
|
||||||
* Seguir, dejar de seguir, reportar como spam y bloquear a un usuario,
|
|
||||||
* Abrir una línea temporal para un usuario, lo que permite obtener todos los Tuits de ese usuario únicamente,
|
|
||||||
* Abrir direcciones URL cuando vayan en un tuit o mensaje directo,
|
|
||||||
* Reproducir varios tipos de archivos o direcciones que contengan audio.
|
|
||||||
* Y más.
|
|
||||||
|
|
||||||
# Tabla de contenidos
|
|
||||||
|
|
||||||
Para poder utilizar una aplicación como TW Blue que te permita gestionar una cuenta de Twitter, primero tienes que estar registrado en esta red social. Esta documentación no tiene como objetivo explicar el procedimiento para hacerlo. Partiremos desde el punto que tienes una cuenta con su respectivo nombre de usuario y contraseña. La documentación cubrirá estas secciones.
|
|
||||||
|
|
||||||
* [Autorizar la aplicación](#autorizar)
|
|
||||||
* [La interfaz del programa](#interfaz)
|
|
||||||
* [Controles](#controles)
|
|
||||||
* [La interfaz gráfica (GUI)](#gui)
|
|
||||||
* [Botones de la aplicación](#botones)
|
|
||||||
* [Menús](#menus)
|
|
||||||
* [Menú aplicación](#app)
|
|
||||||
* [Menú Tuit](#tuit)
|
|
||||||
* [Menú Usuario](#usuario)
|
|
||||||
* [Menú buffer](#buffer)
|
|
||||||
* [Menú ayuda](#ayuda)
|
|
||||||
* [La interfaz No Visible](#interfaz_no_visible)
|
|
||||||
* [Atajos de Teclado para la Interfaz Gráfica](#atajos)
|
|
||||||
* [Atajos de Teclado para la Interfaz no Visible](#atajos_invisibles)
|
|
||||||
* [Listas](#listas)
|
|
||||||
* [Reportando Errores desde la web](#reportar)
|
|
||||||
* [Contacto](#contacto)
|
|
||||||
|
|
||||||
## Autorizando la aplicación {#autorizar}
|
|
||||||
|
|
||||||
Antes de nada, lo primero que se necesita es autorizar al programa para que este pueda acceder a tu cuenta de Twitter, y desde ella realizar lo que le pidas. El proceso de autorización es bastante sencillo, y en ningún momento el programa podrá tener acceso a tus datos como usuario y contraseña. Para autorizar la aplicación, solo tienes que abrir el archivo principal del programa, llamado TW Blue.exe (en algunos PC, solo se muestra como TW Blue).
|
|
||||||
|
|
||||||
Al hacerlo, si no has configurado ninguna vez el programa, se mostrará un cuadro de diálogo donde te informa que serás llevado a Twitter para autorizar la aplicación una vez pulses sobre "aceptar". Para empezar con el proceso de autorización presiona sobre el único botón de ese diálogo.
|
|
||||||
|
|
||||||
A continuación, tu navegador predeterminado se abrirá con la página de Twitter solicitándote autorizar la aplicación. Escribe, si no estás autenticado ya, tu nombre de usuario y contraseña, luego busca el botón autorizar, y presiónalo.
|
|
||||||
|
|
||||||
De la página a la que serás redirigido (si el proceso ha tenido éxito), busca las instrucciones que te proporciona Twitter. En resumen, te dará un código numérico de varios dígitos que deberás pegar en un cuadro de texto que la aplicación ha abierto en otra ventana.
|
|
||||||
|
|
||||||
Pega el código de verificación, y pulsa la tecla Intro.
|
|
||||||
|
|
||||||
Si todo ha salido bien, la aplicación empezará a reproducir un grupo de sonidos en señal que se están actualizando tus datos.
|
|
||||||
|
|
||||||
Cuando termine, el programa reproducirá otro sonido, y el lector de pantalla dirá "listo".
|
|
||||||
|
|
||||||
## La interfaz del programa {#interfaz}
|
|
||||||
|
|
||||||
La forma más simple de describir la interfaz gráfica de la aplicación es la de una ventana con una barra de menú con cinco menús (aplicación, tuit, usuario, buffer y ayuda); una lista de varios elementos y en la mayoría de los casos tres botones. Tuit, retuit y responder. Las acciones para cada uno de estos elementos serán descritas más adelante.
|
|
||||||
|
|
||||||
Los elementos que hay en las listas pueden ser Tuits, mensajes directos o usuarios. TW Blue crea diferentes pestañas para cada lista, pues estos elementos pueden ser Tuits enviados, Tuits recividos en la línea principal, favoritos, o mensajes directos, y cada pestaña tiene un solo tipo de Tuit. Estas pestañas se llaman listas o buffers.
|
|
||||||
|
|
||||||
Para cambiar entre las listas se hace presionando Control+Tab si se desea avanzar, y Control+Shift+Tab para retroceder. En todo momento los lectores de pantalla anunciarán la lista hacia la que se cambie el foco de la aplicación. Aquí están las listas básicas de TW Blue, que aparecen si se usa la configuración por defecto.
|
|
||||||
|
|
||||||
* Principal: Aquí van todos los Tuits que se muestran en la línea principal. Estos son los Tuits de los usuarios a los que sigues.
|
|
||||||
* Menciones: Si un usuario (lo sigas o no) te menciona en Twitter, lo verás en esta lista.
|
|
||||||
* Mensajes directos: Aquí están los mensajes directos (privados) que intercambias con los usuarios que sigues y te siguen. Esta lista solo muestra los mensajes recividos.
|
|
||||||
* Enviados: En esta lista se muestran todos los Tuits y mensajes directos que se han enviado desde tu cuenta.
|
|
||||||
* Favoritos: Aquí verás los Tuits que has marcado como favoritos.
|
|
||||||
* Seguidores: Cuando los usuarios sigan tu cuenta, podrás verlos en esta lista, junto con un poco de información de la cuenta.
|
|
||||||
* Amigos: Igual que la lista anterior, pero estos usuarios son a los que tú sigues.
|
|
||||||
* Eventos: Un evento en TW Blue es "algo" que pase en Twitter. En la línea de eventos, podrás ver registrados los eventos más comunes (p. Ej. Te han comenzado a seguir, han marcado o removido un tweet tuyo de los favoritos, te has suscrito a una lista). Son como pequeñas notificaciones que envía Twitter y TW Blue organiza para que no te pierdas lo que ha pasado con tu cuenta.
|
|
||||||
* Línea temporal de un usuario: Estas son listas que tú deberás crear. Es una lista que contiene únicamente los Tuits de un usuario. Se usan si algún día necesitas o quieres ver los Tuits que ha realizado solo una persona y no deseas buscar por todo tu timeline. Puedes crear tantas como usuarios necesites.
|
|
||||||
* Lista: Una lista es parecida a una línea temporal, pero compuesta por los tweets de cada usuario que forme parte de ella. De momento las listas son una característica experimental de TW Blue. Si experimentas problemas con ellas, por favor escríbenos para contárnoslo.
|
|
||||||
* Búsqueda: Un buffer de búsqueda contiene los resultados de una búsqueda hecha en TW Blue. Las búsquedas pueden ser por tuits, en cuyo caso buscas un término en los tuits relevantes de Twitter, o por usuarios, donde los resultados son nombres de usuario de Twitter.
|
|
||||||
* Favoritos de un usuario: Es posible pedirle a TW Blue que te muestre los tuits que un usuario ha marcado como favoritos.
|
|
||||||
|
|
||||||
Nota: Únicamente para esta versión de TW Blue, los amigos y seguidores actualizarán hasta 400, o cerca a los 400. En la próxima versión proporcionaremos un método para ver los amigos y seguidores sin exponerse tanto a los errores causados por el uso de la API de Twitter, muy frecuente entre personas con más de 600 amigos o seguidores.
|
|
||||||
|
|
||||||
Ten en cuenta que por defecto la configuración solo permite obtener los 200 últimos Tuits para las listas principal, menciones, mensajes directos y líneas temporales. Esto puedes cambiarlo desde el diálogo de configuración. Para los enviados se obtendrán los últimos 200 Tuits y 200 mensajes directos. En versiones futuras se permitirá ajustar este parámetro.
|
|
||||||
|
|
||||||
Si hay una dirección URL en algún tuit, TW Blue intentará abrirla cuando presiones Intro sobre ella. Si hay más de una, te mostrará una lista con todas para que selecciones la que quieras abrir. Si estás en el cuadro de diálogo de los amigos o seguidores, la tecla intro te mostrará detalles del mismo.
|
|
||||||
|
|
||||||
Si pulsas Control+Intro, TW Blue intentará reproducir el audio que tenga el tuit sobre el que está el foco del sistema, siempre que tenga una URL. Si el tuit lleva la etiqueta #audio, un sonido al pasar por él te alertará que es un audio y puedes intentar reproducirlo. No obstante, también puede que no esté etiquetado y que TW Blue pueda reproducirlo, siempre que lleve a una dirección URL donde exista audio.
|
|
||||||
|
|
||||||
## Controles {#controles}
|
|
||||||
|
|
||||||
A partir de la versión 0.36, existe soporte para una interfaz que no requiere de una ventana visible. Esta puede ser activada pulsando Control+m, o seleccionando desde el menú aplicación la opción "Esconder ventana". Esta interfaz se maneja completamente con atajos de teclado. Estos atajos son diferentes a los que se utilizan para la interfaz gráfica. Cada una de ellas podrá utilizar solo los atajos que le correspondan, lo que quiere decir que no se permitirá utilizar los atajos de la interfaz no visible si se tiene activada la interfaz gráfica. En esta sección se detallará tanto la interfaz gráfica como la no visible.
|
|
||||||
|
|
||||||
### Interfaz gráfica (GUI) {#gui}
|
|
||||||
|
|
||||||
Aquí una lista dividida en dos partes. Por un lado, los botones que encontrarás si presionas Tab o Shift+Tab en la interfaz del programa, y por otro, los diferentes elementos que hay en la barra de menú.
|
|
||||||
|
|
||||||
#### Botones de la aplicación {#botones}
|
|
||||||
|
|
||||||
* Twit: Este botón abre el diálogo para escribir un tuit. El mensaje solo debe tener 140 caracteres. Al escribir el caracter número 141, un sonido será reproducido para indicarte que te has pasado del límite permitido por Twitter. Puedes querer acortar o desacortar una URL si la incluye tu tuit a fin de ganar más espacio donde escribir, para eso están los botones con esos nombres. Pulsa Intro para enviar el tuit. Si todo sale bien, el mensaje se enviará y tú escucharás un sonido que te lo confirme, si no, el lector de pantalla te responderá con un error en inglés, que indica por qué no se ha podido enviar el mensaje.
|
|
||||||
* Retuit: Este botón se encarga de reenviar el tuit sobre el que estás leyendo. Al presionarlo se te preguntará si deseas añadirle un comentario al tuit original (citándolo) o simplemente enviarlo como se ha escrito sin añadir nada más.
|
|
||||||
* Responder: Cuando estés visualizando un Tuit, puedes responderle al usuario que lo escribió pulsando sobre este botón. Se abrirá el mismo diálogo de Tuit, pero con el nombre del usuario (por ejemplo @usuario) en el, para que solo escribas el mensaje que quieres responderle. Si en el tuit hay más de un usuario mencionado, pulsa Shift+Tab y pulsa el botón "Mencionar a todos los usuarios". Cuando estés en la lista de amigos o seguidores, este botón se llamará mencionar.
|
|
||||||
* mensaje directo: Exactamente igual que enviar un Tuit, pero es un mensaje privado que solo podrá ver el usuario al que se lo envías. Pulsa Shift+Tab para ver el destinatario de tu mensaje. Si en el Tuit donde estabas para enviar el mensaje había más de un usuario mencionado, puedes navegar con las flechas de arriba y abajo para seleccionar otro, o escribir tú mismo el usuario (sin el signo de arroba).
|
|
||||||
|
|
||||||
Ten en cuenta que los botones aparecerán según las acciones que se puedan hacer en la lista donde estés. Por ejemplo, en la línea principal, menciones, enviados, favoritos y las líneas temporales de los usuarios podrás ver los cuatro botones; mientras que en la lista de mensajes directos solo estará disponible el botón de "Mensaje Directo" y "tuit", y en las listas de amigos y seguidores, se verá el botón para "Twit" y el de "Mensaje directo" junto a "mencionar".
|
|
||||||
|
|
||||||
#### Menús {#menus}
|
|
||||||
|
|
||||||
En la parte superior de la ventana del programa podrás encontrar una barra de menú que hace las mismas cosas, y algunas cuantas más. A la barra de menú se accede presionando la tecla ALT, y cuenta en este momento con cuatro menús para diferentes acciones: Aplicación, Tuit, usuario y Ayuda. En esta sección se describen las acciones para cada uno de ellos.
|
|
||||||
|
|
||||||
##### Menú aplicación {#app}
|
|
||||||
|
|
||||||
* Actualizar Perfil: Abre un diálogo desde donde se podrá actualizar parte de tu información en Twitter. Nombre, ubicación, dirección URL y descripción. Si ya tienes alguno de estos campos actualmente en el perfil se llenarán automáticamente con lo que tiene tu configuración de Twitter. También podrás subir una foto a tu perfil.
|
|
||||||
* Esconder Ventana: Desactiva la interfaz gráfica. Lee el apartado sobre la interfaz no visible para más detalles sobre este comportamiento.
|
|
||||||
* Búsqueda: Muestra un cuadro de diálogo desde donde puedes buscar por tuits o por usuarios en twitter.
|
|
||||||
* Gestor de listas: Para poder utilizar las listas de Twitter, primero necesitarás crearlas. Este diálogo permite ver tus listas, editarlas, crearlas, borrarlas y, opcionalmente, verlas en buffers tal como lo harías con las líneas temporales.
|
|
||||||
* Tutorial de sonidos: Abre un diálogo donde verás una lista de los sonidos de TW blue, para que puedas aprenderlos y no te cueste trabajo familiarizarte con TW Blue.
|
|
||||||
* Preferencias: Abre un diálogo de configuración desde donde se pueden controlar algunos aspectos del programa. Las opciones no necesitan de explicación.
|
|
||||||
* Salir: pregunta si quieres salir o no del programa. Si la respuesta es que sí, cierra la aplicación.
|
|
||||||
|
|
||||||
##### Menú Tuit {#tuit}
|
|
||||||
|
|
||||||
* Las primeras opciones del menú son Twit, responder y retuit, que corresponden a los botones del mismo nombre.
|
|
||||||
* Marcar como favorito: Marca el tuit que estés viendo como favorito.
|
|
||||||
* Quitar tuit de favoritos: Elimina el tuit de tus favoritos. Esto no significa que se borra de Twitter, solo deja de estar en tu lista de favoritos.
|
|
||||||
* Ver Tuit: Abre un diálogo donde puedes ver el Tuit, mensaje directo, amigo o seguidor sobre el que esté el foco de la aplicación. Puedes leer el texto con los cursores. El diálogo es el mismo que el que se usa para escribir un Tuit.
|
|
||||||
* Eliminar: Elimina el Tuit o mensaje directo sobre el que estés, borrándolo definitivamente de Twitter y qitándolo de tus listas. Ten en cuenta que en el caso de los Tuits, Twitter solo permite borrar los que tú mismo has escrito.
|
|
||||||
|
|
||||||
##### Menú usuario {#usuario}
|
|
||||||
|
|
||||||
Ten en cuenta que las primeras seis opciones de este menú abren un mismo diálogo. Este diálogo tiene un cuadro de edición donde puedes seleccionar el usuario sobre el que deseas actuar, bien con los cursores arriba y abajo o escribiendo tú mismo el nombre. Después, hay un grupo de botones de radio para seguir, dejar de seguir, silenciar, des-silenciar, reportar como Spam y bloquear. Si seleccionas desde el menú la opción seguir, el botón del cuadro de diálogo estará marcado con esa opción, así como sucederá respectivamente con dejar de seguir, reportar como Spam y bloquear. Pulsa el botón Aceptar para que el programa trate de hacer lo que le pides. Si no se ha podido, escucharás el error en inglés.
|
|
||||||
|
|
||||||
A continuación se describen las opciones restantes para este menú:
|
|
||||||
|
|
||||||
* Mensaje Directo: La misma acción que el botón.
|
|
||||||
* Añadir a lista: Para que puedas ver los tweets de un usuario en tus listas, primero hay que añadirlo. Esta opción abrirá un diálogo desde donde puedes seleccionar al usuario que deseas añadir, para después abrir otra ventana donde puedes seleccionar la lista a la cual añadir a ese usuario. Una vez hecho esto, la lista contendrá un nuevo usuario y podrás ver sus tweets.
|
|
||||||
* Ver Perfil del usuario: Abre un diálogo desde donde te permite seleccionar el usuario al que quieres ver el perfil.
|
|
||||||
* Línea temporal: Abre un diálogo desde donde puedes seleccionar el usuario para el que se creará la línea temporal. Al presionar intro, se creará. Si se hace una línea temporal de un usuario que no tenga Tuits, el programa fallará. Si se crea una línea que ya existe el programa te avisará y no permitirá crearla de nuevo.
|
|
||||||
* Ver favoritos: Abre un buffer para seguir los favoritos que marca el usuario seleccionado.
|
|
||||||
|
|
||||||
##### Menú Buffer {#buffer}
|
|
||||||
|
|
||||||
* Silenciar: Silencia completamente el buffer, con lo que no escucharás sonido alguno cuando nuevos elementos aparezcan.
|
|
||||||
* Leer automáticamente tuits para este buffer: Esta opción activa o desactiva la lectura automática de tuits. Si está activada, el lector de pantalla o la voz Sapi5 (si está activada una) leerá automáticamente los nuevos tuits conforme estos vayan llegando al buffer.
|
|
||||||
* Limpiar Buffer: Vacía los elementos de este buffer.
|
|
||||||
* Eliminar buffer: Borra la lista sobre la que te encuentras actualmente.
|
|
||||||
|
|
||||||
##### Menú Ayuda {#ayuda}
|
|
||||||
|
|
||||||
* Documentación: Abre este archivo, donde puedes leer algunos conceptos interesantes del programa.
|
|
||||||
* ¿Qué hay de nuevo en esta versión?: Abre un documento con la lista de cambios desde la versión actual, hasta la primera en existencia.
|
|
||||||
* Buscar actualizaciones: Cada que se abre el programa él mismo busca automáticamente si hay una nueva versión. Si lo hay, te preguntará si quieres descargarla; si aceptas, TW Blue descargará la actualización, la instalará y te pedirá reiniciarla (algo que hace automáticamente). Esta opción comprueba si hay actualizaciones sin tener que reiniciar la aplicación.
|
|
||||||
* Sitio web de TW Blue. Ve a nuestra [página principal](http://twblue.com.mx) donde podrás encontrar toda la información y descargas relativas a TW Blue, así como participar de la comunidad.
|
|
||||||
* Reportar un error: Lanza un diálogo desde donde puedes reportar un error solo llenando un par de campos. El título y una pequeña descripción de lo que pasó. Al pulsar en "enviar" el error se reportará. Si no se ha podido el programa te mostrará un mensaje informándolo.
|
|
||||||
* Sobre TW Blue: Muestra información de créditos del programa.
|
|
||||||
|
|
||||||
### Interfaz no visible {#interfaz_no_visible}
|
|
||||||
|
|
||||||
Si presionas Control+M, o si desde el menú aplicación seleccionas esconder ventana, estarás activando una interfaz a la que no se podrá acceder por la manera convencional, porque no se ve.
|
|
||||||
|
|
||||||
En la interfaz no visible todo lo que hagas será mediante atajos de teclado, incluso para recorrer las listas. Eventualmente se abrirán diálogos y estos sí serán visibles, pero la ventana principal de la aplicación no. Ve a la sección de atajos de teclado de la interfaz no visible para saber cuales puedes usar de momento.
|
|
||||||
|
|
||||||
### Atajos de teclado para la Interfaz Gráfica {#atajos}
|
|
||||||
|
|
||||||
Además de los botones y menús, la mayoría de las acciones pueden hacerse presionando una combinación de teclado. Aquí están las existentes en este momento:
|
|
||||||
|
|
||||||
* Intro: Abrir una dirección URL. Si hay más de una podrás ver una lista que te permitirá seleccionar la que quieras. Si estás en la lista de amigos o seguidores, mostrará detalles del seleccionado.
|
|
||||||
* Control+Intro: Intenta reproducir un audio si en el Tuit hay una dirección URL.
|
|
||||||
* F5: Baja un 5% el volumen de los sonidos. Esto afecta a los sonidos que reproduce el programa y al audio que puedas escuchar a través de él.
|
|
||||||
* F6: Sube un 5% el volumen de los sonidos de la aplicación.
|
|
||||||
* Control+N: Abre el diálogo para escribir un nuevo Tuit.
|
|
||||||
* Control+M: Oculta la ventana.
|
|
||||||
* Control+Q: Sale de la aplicación.
|
|
||||||
* Control+R: Abre el diálogo para responder.
|
|
||||||
* Control+Shift+R: Equivalente a la acción Retuit.
|
|
||||||
* Control+D: Enviar mensaje directo.
|
|
||||||
* Control+F: Marcar como favorito.
|
|
||||||
* Control+Shift+F: Quitar de favoritos.
|
|
||||||
* Control+Shift+V: Ver Tuit.
|
|
||||||
* Control+S: Seguir a un usuario.
|
|
||||||
* Control+Shift+S: Dejar de seguir a un usuario.
|
|
||||||
* Control+K: Bloquear a un usuario.
|
|
||||||
* Control+Shift+K: Reportar como Spam.
|
|
||||||
* Control+I: Abrir línea temporal a un usuario.
|
|
||||||
* Control+Shift+I: Eliminar línea temporal.
|
|
||||||
* Control+p: Editar tu perfil.
|
|
||||||
* Suprimir: Eliminar tuit o mensaje directo.
|
|
||||||
* Shift+suprimir: vacía el buffer, quitando todos los elementos hasta ese entonces. Esto ocurre sin borrar nada de Twitter.
|
|
||||||
|
|
||||||
### Atajos de teclado para la Interfaz no Visible {#atajos_invisibles}
|
|
||||||
|
|
||||||
Estos son los atajos de teclado que puedes usar desde la interfaz no visible. Ten en cuenta que cuando la vista de la interfaz gráfica esté activada ninguno de ellos podrá usarse. Al decir "windows", nos estamos refiriendo a la tecla de Windows izquierda.
|
|
||||||
|
|
||||||
* Control+Windows+Flecha Arriba: Va arriba en la lista actual.
|
|
||||||
* Control+Windows+Flecha abajo: Va hacia abajo en la lista actual.
|
|
||||||
* Control+Windows+Izquierda: Se desplaza a la pestaña de la izquierda.
|
|
||||||
* Control+Windows+Derecha: Se desplaza hacia la pestaña de la derecha.
|
|
||||||
* Control+Windows+Inicio: Ir al primer elemento de la lista.
|
|
||||||
* Control+Windows+Fin: Ir al final de la lista.
|
|
||||||
* Control+Windows+Avance de página: Ir 20 elementos hacia abajo en la lista actual.
|
|
||||||
* Control+Windows+Retroceso de página: ir 20 elementos hacia arriba en la lista actual.
|
|
||||||
* Control+Windows+Alt+Flecha Arriba: Subir volumen un 5%.
|
|
||||||
* Control+Windows+Alt+Flecha Abajo: Bajar volumen un 5%.
|
|
||||||
* Control+Windows+Intro: Abrir URL en el tuit, o ver detalles del usuario si estás en la lista de amigos o seguidores.
|
|
||||||
* Control+Windows+Alt+Intro: Intentar reproducir un audio.
|
|
||||||
* Control+Windows+M: Muestra la interfaz gráfica, desactivando la no visible.
|
|
||||||
* Control+Windows+N: Hacer un nuevo Tuit.
|
|
||||||
* Control+Windows+R: Responder a un tuit.
|
|
||||||
* Control+Windows+Shift+R: Hacer un retuit.
|
|
||||||
* Control+Windows+D: Enviar un mensaje directo.
|
|
||||||
* Control+Windows+Suprimir: Eliminar un tuit o mensaje directo.
|
|
||||||
* control+win+Shift+suprimir: vacía el buffer, quitando todos los elementos hasta ese entonces. Esto ocurre sin borrar nada de Twitter.
|
|
||||||
* Windows+Alt+F: Marcar como favorito.
|
|
||||||
* Windows+Alt+Shift+F: Quitar de favoritos.
|
|
||||||
* Control+Windows+S: Seguir a un usuario.
|
|
||||||
* Control+Windows+Shift+S: Dejar de seguir a alguien.
|
|
||||||
* Control+Windows+Alt+N: Ver detalles de un usuario,
|
|
||||||
* Control+Windows+V: Ver tuit en un cuadro de texto.
|
|
||||||
* Control+Windows+I: Abrir línea temporal.
|
|
||||||
* Control+Windows+Shift+I: Eliminar línea temporal de un usuario.
|
|
||||||
* Alt+Windows+P: Editar tu perfil.
|
|
||||||
* Control+win+espacio: ver tweet actual.
|
|
||||||
* Control+win+c: Copiar tweet al portapapeles.
|
|
||||||
* Control+windows+a: Añadir a un usuario a la lista.
|
|
||||||
* Control+shift+windows+a: qitar de la lista.
|
|
||||||
* Control+Windows+Shift+Flecha arriba: Ir un tuit hacia arriba en la conversación.
|
|
||||||
* Control+Windows+Flecha Abajo: Ir un tuit hacia abajo en la conversación.
|
|
||||||
* Control+Windows+Shift+M: Activar o desactivar el sonido para el buffer actual.
|
|
||||||
* Windows+Alt+M: Activar o desactivar el silencio global de TW Blue.
|
|
||||||
* Control+Windows+E: Activar o desactivar la lectura automática de los tuits en el buffer actual.
|
|
||||||
* Control+windows+Guion: buscar en Twitter.
|
|
||||||
* Control+Windows+F4: Cerrar el programa.
|
|
||||||
|
|
||||||
## Listas {#listas}
|
|
||||||
|
|
||||||
Una de las características más interesantes de Twitter son las listas, ya que son una manera de mantenerse actualizado sin tener que leer los tweets de todos los usuarios a los que sigues. Con una lista de Twitter solo verás los tweets de sus miembros (la gente que está dentro de la lista). Es parecido a una línea temporal, pero para muchos más usuarios.
|
|
||||||
|
|
||||||
En TW blue hemos empezado a dar soporte para esta característica. De momento vamos poco a poco, pero ya es posible usar esta función. Te presentamos los pasos que hay que dar para poder tener una lista abierta en TW Blue.
|
|
||||||
|
|
||||||
* Primero necesitarás ir al gestor de listas, ubicado bajo el menú aplicación.
|
|
||||||
* en el gestor de listas podrás ver todas las listas a las que estás unido, empezando por las que tú has creado. Si no ves ninguna lista en este diálogo, significa que no has creado ni te has unido a ninguna lista. Está bien.
|
|
||||||
* Verás un grupo de botones que se explican por sí solos: Crear nueva lista, editar, eliminar, abrir en buffer (este quizá es el menos claro, se refiere a abrir un nuevo buffer para que TW Blue actualice los tweets de la lista, como cuando pasa con las líneas temporales).
|
|
||||||
|
|
||||||
Una vez que hayas creado una nueva lista, no deberías abrirla en buffer. Al menos no de inmediato, porque en este momento no tiene miembro alguno y eso significa que cuando se carguen los tweets para empezar a actualizarla no verás nada. Es recomendable primero añadir a gente a la lista, tal como sigue:
|
|
||||||
|
|
||||||
* Cuando hayas cerrado el gestor de listas y estés navegando por entre los tweets de los usuarios, busca el usuario al que quieres añadir a la lista.
|
|
||||||
* Una vez encontrado, presiona el atajo Ctrl+Win+A o ve al menú usuario y selecciona la opción "Añadir a lista".
|
|
||||||
* Lo siguiente que verás es un diálogo que te permitirá seleccionar el usuario, asegúrate que el que está como predeterminado es el que deseas, o cámbialo si es necesario, y presiona Aceptar.
|
|
||||||
* Ahora verás otro diálogo, pero aquí están todas tus listas. Selecciona una (simplemente lleva el cursor hacia ella), y presiona el botón añadir.
|
|
||||||
* Para qitar a un usuario de una lista repite el mismo proceso, pero presiona Control+Win+Shift+A o selecciona la opción "Quitar de lista", y en el diálogo de las listas presiona sobre el botón "remover".
|
|
||||||
|
|
||||||
## Reportando Errores Desde la Web {#reportar}
|
|
||||||
|
|
||||||
Nota: Si estás usando el programa también puedes reportar un error desde el mismo, usando para ello la opción del menú ayuda. Este proceso solo te pide llenar dos cuadros de edición, y se encarga del resto. Estos pasos están escritos para quienes no pueden abrir el programa, no lo tienen en uso en este momento o sencillamente quieran reportar desde la web en lugar del sistema integrado de reporte de errores.
|
|
||||||
|
|
||||||
Las cosas en este mundo (sí, incluidos los programas informáticos) están muy lejos de ser perfectas, con lo que a menudo te encontrarás con errores no previstos en la aplicación. Pero como la intención es siempre mejorar, eres libre (es más, sería genial que lo hicieras) de reportar los errores que vayas encontrando del programa para que se puedan revisar y eventualmente corregir.
|
|
||||||
|
|
||||||
Para entrar a la web de reporte de incidencias, sigue [Este enlace.](http://twblue.com.mx/errores/bug_report_page.php) Es una web con un formulario donde tienes que llenar varios campos. Solo tres de ellos son realmente obligatorios (los que tienen marcado un asterisco), pero entre más campos puedas llenar, será mejor.
|
|
||||||
|
|
||||||
Aquí están los diferentes campos del formulario y lo que deberías introducir en cada uno de ellos. Recuerda que son obligatorios solamente los campos marcados con un asterisco (*):
|
|
||||||
|
|
||||||
* Categoría: Este cuadro combinado permite seleccionar a qué categoría asignar el error. Puede ser a la categoría General, si es un error del programa, o a documentación, si has encontrado un error en este archivo o en la lista de cambios. Este campo es obligatorio.
|
|
||||||
* Reproducibilidad: Aquí deberías indicar qué tan fácil o no es de reproducir el error. Las opciones disponibles son Desconocido, No reproducible, No se ha intentado (por defecto), aleatorio, a veces o siempre. Dependiendo de si se puede reproducir el error o no, deberías indicar lo que se parezca más a tu caso. Si estás solicitando una nueva funcionalidad, no importa este cuadro combinado.
|
|
||||||
* Severidad: Aquí se selecciona que tanto afecta esto al programa. Las opciones disponibles son funcionalidad (selecciona esto para solicitar una nueva funcionalidad), Trivial, Texto, Ajuste, Menor, Mayor, fallo o bloqueo. Nota que las opciones aumentan de nivel. Selecciona lo que más creas. Si no estás seguro de que seleccionar puedes dejarlo como está.
|
|
||||||
* Prioridad: En este cuadro se selecciona la opción de acuerdo con la importancia del error o funcionalidad solicitada. Las opciones disponibles son Ninguna, baja, normal, alta, hurgente e inmediata.
|
|
||||||
* Seleccionar Perfil: Aquí puedes escojer entre la configuración de arquitectura (32 o 64 bits), y el sistema operativo (Windows siete de momento). Si no, puedes llenar los tres cuadros de edición que están en la siguiente tabla con tus datos en específico.
|
|
||||||
* Versión del producto: Selecciona la versión del programa que estás utilizando para poder averiguar donde se ha generado el error. Este cuadro combinado tendrá la lista de las versiones en orden. Si bien no es obligatorio, ayudaría mucho a resolver más rápidamente el error.
|
|
||||||
* Resumen: Un título para el error, que explique en pocas palabras qué ocurre. Es un cuadro de texto obligatorio.
|
|
||||||
* Descripción: Este campo también obligatorio, te pide que describas con más detalles qué fue lo que ha ocurrido con el programa.
|
|
||||||
* Pasos para reproducir: Este campo de texto te sirve si sabes como hacer que la aplicación genere el error. Esto no es obligatorio, pero ayudaría mucho conocer como hacer que el programa tenga este error para rastrearlo mejor.
|
|
||||||
* Información adicional: Si tienes un comentario o nota que añadir, aquí puede ir. No es obligatorio.
|
|
||||||
* Subir archivo: Puedes subir aquí el archivo TW Blue.exe.log que se creó con el error que el programa tuvo. No es obligatorio.
|
|
||||||
* Visibilidad: Selecciona si quieres que el error sea público o privado. Por defecto es público, y es recomendable que así continúe.
|
|
||||||
* Enviar reporte. Presiona aquí para publicar el error y que este sea atendido.
|
|
||||||
|
|
||||||
Muchas gracias por participar reportando errores y probando las funciones nuevas.
|
|
||||||
|
|
||||||
## Contacto {#contacto}
|
|
||||||
|
|
||||||
Si lo que se expone en este documento no es suficiente, si deseas colaborar de alguna otra forma o si simplemente deseas mantenerte en contacto con quien hace esta aplicación, sigue a la cuenta [@tw_blue2](https://twitter.com/tw_blue2) o a [@manuelcortez00.](https://twitter.com/manuelcortez00) También puedes visitar nuestro [Sitio web](http://twblue.com.mx)
|
|
||||||
|
|
||||||
---
|
|
||||||
Copyright © 2013-2014. Manuel Cortéz.
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: twblue-documentation 0.46\n"
|
"Project-Id-Version: twblue-documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-08 10:32+0300\n"
|
"PO-Revision-Date: 2018-08-08 10:32+0300\n"
|
||||||
"Last-Translator: Florian Ionașcu <florianionascu@hotmail.com>\n"
|
"Last-Translator: Florian Ionașcu <florianionascu@hotmail.com>\n"
|
||||||
"Language-Team: Spanish <manuel@manuelcortez.net>\n"
|
"Language-Team: Spanish <manuel@manuelcortez.net>\n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-15 12:20+0400\n"
|
"PO-Revision-Date: 2018-08-15 12:20+0400\n"
|
||||||
"Last-Translator: Наталья Хедлунд <natalia.hedlund@gmail.com>\n"
|
"Last-Translator: Наталья Хедлунд <natalia.hedlund@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-08-14 21:44+0400\n"
|
"PO-Revision-Date: 2018-08-14 21:44+0400\n"
|
||||||
"Last-Translator: Valeria <luciana.lu3a@gmail.com>\n"
|
"Last-Translator: Valeria <luciana.lu3a@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estándar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2021-06-27 04:17+0100\n"
|
"PO-Revision-Date: 2021-06-27 04:17+0100\n"
|
||||||
"Last-Translator: Nikola Jović <wwenikola123@gmail.com>\n"
|
"Last-Translator: Nikola Jović <wwenikola123@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estándar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2021-06-27 01:40+0100\n"
|
"PO-Revision-Date: 2021-06-27 01:40+0100\n"
|
||||||
"Last-Translator: Nikola Jović <wwenikola123@gmail.com>\n"
|
"Last-Translator: Nikola Jović <wwenikola123@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2018-01-05 17:01+0300\n"
|
"PO-Revision-Date: 2018-01-05 17:01+0300\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
Binary file not shown.
@@ -5,7 +5,7 @@
|
|||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: TW Blue documentation 0.46\n"
|
"Project-Id-Version: TW Blue documentation 0.46\n"
|
||||||
"POT-Creation-Date: 2019-03-17 13:34+Hora estndar romance\n"
|
"POT-Creation-Date: 2019-03-17 13:34\n"
|
||||||
"PO-Revision-Date: 2019-02-03 17:01+0300\n"
|
"PO-Revision-Date: 2019-02-03 17:01+0300\n"
|
||||||
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Documentation for TWBlue - 0.88
|
Documentation for TWBlue
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ You can log into several Twitter accounts simultaneously. The program refers to
|
|||||||
|
|
||||||
Your default browser will open on the Twitter page to request authorisation. Enter your username and password into the appropriate edit fields if you're not already logged in, select the authorise button, and press it.
|
Your default browser will open on the Twitter page to request authorisation. Enter your username and password into the appropriate edit fields if you're not already logged in, select the authorise button, and press it.
|
||||||
|
|
||||||
Once you've authorised your twitter account, the website will redirect you to a page which will notify you that TWBlue has been authorised successfully. Now you are able to close the page by pressing ALT+F4 which will return you to the Session Manager. On the session list, you will see a new item temporarily called "Authorised account x" -where x is a number. The session name will change once you open that session.
|
Once you've authorised your twitter account, the website will redirect you to a page which will notify you that TWBlue has been authorised successfully. On this page, you will be shown a code composed of several numbers that you must paste in the TWBlue authorization dialogue in order to allow the application to access your account. Once you have pasted the code in the corresponding text field, press enter to finish the account setup and go back to the session manager. On the session list, you will see a new item temporarily called "Authorised account x" -where x is a number. The session name will change once you open that session.
|
||||||
|
|
||||||
To start running TWBlue, press the Ok button in the Session Manager dialogue. By default, the program starts all the configured sessions automatically, however, you can change this behavior.
|
To start running TWBlue, press the Ok button in the Session Manager dialogue. By default, the program starts all the configured sessions automatically, however, you can change this behavior.
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ Before starting to describe TWBlue's usage, we'll explain some concepts that wil
|
|||||||
|
|
||||||
### Buffer
|
### Buffer
|
||||||
|
|
||||||
A buffer is a list of items to manage the data which arrives from Twitter, after being processed by the application. When you configure a new session on TWBlue and start it, many buffers are created. Each of them may contain some of the items which this program works with: Tweets, direct messages, users, trends or events. According to the buffer you are focusing, you will be able to do different actions with these items.
|
A buffer is a list of items to manage the data which arrives from Twitter, after being processed by the application. When you configure a new session on TWBlue and start it, many buffers are created. Each of them may contain some of the items which this program works with: Tweets, direct messages, users, trends or. According to the buffer you are focusing, you will be able to do different actions with these items.
|
||||||
|
|
||||||
The following is a description for every one of TWBlue's buffers and the kind of items they work with.
|
The following is a description for every one of TWBlue's buffers and the kind of items they work with.
|
||||||
|
|
||||||
@@ -69,17 +69,17 @@ The following is a description for every one of TWBlue's buffers and the kind of
|
|||||||
* Followers: when users follow you, you'll be able to see them on this buffer, with some of their account details.
|
* Followers: when users follow you, you'll be able to see them on this buffer, with some of their account details.
|
||||||
* Friends: the same as the previous buffer, but these are the users you follow.
|
* Friends: the same as the previous buffer, but these are the users you follow.
|
||||||
* User timelines: these are buffers you may create. They contain only the tweets by a specific user. They're used so you can see the tweets by a single person and you don't want to look all over your timeline. You may create as many as you like.
|
* User timelines: these are buffers you may create. They contain only the tweets by a specific user. They're used so you can see the tweets by a single person and you don't want to look all over your timeline. You may create as many as you like.
|
||||||
* Events: An event is anything that happens on Twitter, such as when someone follows you, when someone adds or removes one of your tweets from their likes list, or when you subscribe to a list. There are many more, but the program shows the most common ones in the events buffer so that you can easily keep track of what is happening on your account.
|
|
||||||
* Lists: A list is similar to a user timeline, except that you can configure it to contain tweets from multiple users.
|
* Lists: A list is similar to a user timeline, except that you can configure it to contain tweets from multiple users.
|
||||||
* Search: A search buffer contains the results of a search operation.
|
* Search: A search buffer contains the results of a search operation.
|
||||||
* User likes: You can have the program create a buffer containing tweets liked by a particular user.
|
* User likes: You can have the program create a buffer containing tweets liked by a particular user.
|
||||||
|
* Followers or following timeline: You can have TWBlue create a buffer containing all users who follow, or are followed by a specific user.
|
||||||
* Trending Topics: a trend buffer shows the top ten most used terms in a geographical region. This region may be a country or a city. Trends are updated every five minutes.
|
* Trending Topics: a trend buffer shows the top ten most used terms in a geographical region. This region may be a country or a city. Trends are updated every five minutes.
|
||||||
|
|
||||||
If a tweet contains a URL, you can press enter in the GUI or Control + Windows + Enter in the invisible interface to open it. If it contains audio, you can press Control + Enter or Control + Windows + Alt + Enter to play it, respectively. TWBlue will play a sound if the tweet contains the \#audio hashtag, but there may be tweets which contain audio without this. Finally, if a tweet contains geographical information, you can press Control + Windows + G in the invisible interface to retrieve it.
|
If a tweet contains a URL, you can press enter in the GUI or Control + Windows + Enter in the invisible interface to open it. If it contains video or audio, including live stream content, you can press Control + Enter or Control + Windows + Alt + Enter to play it, respectively. TWBlue will play a sound if the tweet contains video metadata or the \#audio hashtag, but there may be tweets which contain media without this. Finally, if a tweet contains geographical information, you can press Control + Windows + G in the invisible interface to retrieve it.
|
||||||
|
|
||||||
### Username fields
|
### Username fields
|
||||||
|
|
||||||
These fields accept a Twitter username (without the at sign) as the input. They are present in the send direct message and the user actions dialogue boxes. Those dialogues will be discussed later. The initial value of these fields depends on where they were opened from. They are prepopulated with the username of the sender of the focused tweet (if they were opened from the home and sent timelines, from users' timelines or from lists), the sender of the focused direct message (if from the received or sent direct message buffers) or in the focused user (if from the followers' or friends' buffer). If one of those dialogue boxes is opened from a tweet, and if there are more users mentioned in it, you can use the arrow keys to switch between them. Alternatively, you can also type a username.
|
These fields accept a Twitter username (without the at sign) as the input. They are present in the send direct message, the user actions dialogue and the user alias dialogue boxes, to name a few examples. Those dialogues will be discussed later. The initial value of these fields depends on where they were opened from. They are prepopulated with the username of the sender of the focused tweet (if they were opened from the home and sent timelines, from users' timelines or from lists), the sender of the focused direct message (if from the received or sent direct message buffers) or in the focused user (if from the followers' or friends' buffer). If one of those dialogue boxes is opened from a tweet, and if there are more users mentioned in it, you can use the arrow keys to switch between them. Alternatively, you can also type a username.
|
||||||
|
|
||||||
## The program's interfaces
|
## The program's interfaces
|
||||||
|
|
||||||
@@ -98,9 +98,9 @@ In summary, the GUI contains two core components. These are the controls you wil
|
|||||||
|
|
||||||
#### Buttons in the application
|
#### Buttons in the application
|
||||||
|
|
||||||
* Tweet: this button opens up a dialogue box to write your tweet. Normal tweets must not exceed 280 characters. However you can press the long tweet checkbox and your tweet will be posted throught Twishort, wich will allow you to write longer tweets (10000 characters). If you write past this limit, a sound will play to warn you. Note that the character count is displayed in the title bar. You may use the shorten and expand URL buttons to comply with the character limit. You can upload a picture, check spelling, attach audio or translate your message by selecting one of the available buttons in the dialogue box. In addition, you can autocomplete the entering of users by pressing Alt + C or the button for that purpose if you have the database of users configured. Press enter to send the tweet. If all goes well, you'll hear a sound confirming it. Otherwise, the screen reader will speak an error message in English describing the problem.
|
* Tweet: this button opens up a dialogue box to write your tweet. Normal tweets must not exceed 280 characters. However you can press the long tweet checkbox and your tweet will be posted throught Twishort, wich will allow you to write longer tweets (10000 characters). If you write past this limit, a sound will play to warn you. Note that the character count is displayed in the title bar. You can upload a picture, check spelling, attach audio or translate your message by selecting one of the available buttons in the dialogue box. In addition, you can autocomplete the entering of users by pressing Alt + C or the button for that purpose if you have the database of users configured. Press enter to send the tweet. If all goes well, you'll hear a sound confirming it. Otherwise, the screen reader will speak an error message in English describing the problem.
|
||||||
* Retweet: this button retweets the message you're reading. After you press it, if you haven't configured the application not to do so, you'll be asked if you want to add a comment or simply send it as written. If you choose to add a comment, it will post a quoted tweet, that is, the comment with a link to the originating tweet.
|
* Retweet: this button retweets the message you're reading. After you press it, if you haven't configured the application not to do so, you'll be asked if you want to add a comment or simply send it as written. If you choose to add a comment, it will post a quoted tweet, that is, the comment with a link to the originating tweet.
|
||||||
* Reply: when you're viewing a tweet, you can reply to the user who sent it by pressing this button. A dialogue will open up similar to the one for tweeting. If there are more users referred to in the tweet, you can press tab and activate the mention to all checkbox, or enabling checkbox for the users you want to mention separately. When you're on the friends or followers lists, the button will be called mention instead.
|
* Reply: when you're viewing a tweet, you can reply to the user who sent it by pressing this button. A dialogue will open up similar to the one for tweeting. If there are more users referred to in the tweet, you can press tab and activate the mention to all checkbox, or enabling checkbox for the users you want to mention separately. Note, however, that sometimes -especially when replying to a retweet or quoted tweet, the user who made the retweet or quote may also be mentioned. This is done by Twitter automatically. When you're on the friends or followers lists, the button will be called mention instead.
|
||||||
* Direct message: exactly like sending a tweet, but it's a private message which can only be read by the user you send it to. Press shift-tab twice to see the recipient. If there were other users mentioned in the tweet you were reading, you can arrow up or down to choose which one to send it to, or write the username yourself without the at sign. In addition, you can autocomplete the entering of users by pressing Alt + C or the button for that purpose if you have the database of users configured.
|
* Direct message: exactly like sending a tweet, but it's a private message which can only be read by the user you send it to. Press shift-tab twice to see the recipient. If there were other users mentioned in the tweet you were reading, you can arrow up or down to choose which one to send it to, or write the username yourself without the at sign. In addition, you can autocomplete the entering of users by pressing Alt + C or the button for that purpose if you have the database of users configured.
|
||||||
|
|
||||||
Bear in mind that buttons will appear according to which actions are possible on the list you are browsing. For example, on the home timeline, mentions, sent, likes and user timelines you will see the four buttons, while on the direct messages list you'll only get the direct message and tweet buttons, and on friends and followers lists the direct message, tweet, and mention buttons will be available.
|
Bear in mind that buttons will appear according to which actions are possible on the list you are browsing. For example, on the home timeline, mentions, sent, likes and user timelines you will see the four buttons, while on the direct messages list you'll only get the direct message and tweet buttons, and on friends and followers lists the direct message, tweet, and mention buttons will be available.
|
||||||
@@ -116,6 +116,7 @@ Visually, Towards the top of the main application window, can be found a menu ba
|
|||||||
* Hide window: turns off the Graphical User Interface. Read the section on the invisible interface for further details.
|
* Hide window: turns off the Graphical User Interface. Read the section on the invisible interface for further details.
|
||||||
* Search: shows a dialogue box where you can search for tweets or users on Twitter.
|
* Search: shows a dialogue box where you can search for tweets or users on Twitter.
|
||||||
* Lists Manager: This dialogue box allows you to manage your Twitter lists. In order to use them, you must first create them. Here, you can view, edit, create, delete or, optionally, open them in buffers similar to user timelines.
|
* Lists Manager: This dialogue box allows you to manage your Twitter lists. In order to use them, you must first create them. Here, you can view, edit, create, delete or, optionally, open them in buffers similar to user timelines.
|
||||||
|
* Manage user aliases: Opens up a dialogue where you can manage user aliases for the active session. In this dialog you can add new aliases, as well as edit and delete existing ones.
|
||||||
* Edit keystrokes: this opens a dialogue where you can see and edit the shortcuts used in the invisible interface.
|
* Edit keystrokes: this opens a dialogue where you can see and edit the shortcuts used in the invisible interface.
|
||||||
* Account settings: Opens a dialogue box which lets you customize settings for the current account.
|
* Account settings: Opens a dialogue box which lets you customize settings for the current account.
|
||||||
* Global settings: Opens a dialogue which lets you configure settings for the entire application.
|
* Global settings: Opens a dialogue which lets you configure settings for the entire application.
|
||||||
@@ -145,6 +146,7 @@ Visually, Towards the top of the main application window, can be found a menu ba
|
|||||||
* Ignore tweets from this client: Adds the client from which the focused tweet was sent to the ignored clients list.
|
* Ignore tweets from this client: Adds the client from which the focused tweet was sent to the ignored clients list.
|
||||||
* View timeline: Lets you open a user's timeline by choosing the user in a dialog box. It is created when you press enter. If you invoke this option relative to a user that has no tweets, the operation will fail. If you try creating an existing timeline the program will warn you and will not create it again.
|
* View timeline: Lets you open a user's timeline by choosing the user in a dialog box. It is created when you press enter. If you invoke this option relative to a user that has no tweets, the operation will fail. If you try creating an existing timeline the program will warn you and will not create it again.
|
||||||
* Direct message: same action as the button.
|
* Direct message: same action as the button.
|
||||||
|
* Add Alias: An user alias allows you to rename user's display names on Twitter, so the next time you'll read an user it will be announced as you configured. This feature works only if you have set display screen names unchecked, in account settings.
|
||||||
* Add to List: In order to see someone's tweets in one or more of your lists, you must add them first. In the dialogue box that opens after selecting the user, you will be asked to select the list you wish to add the user to. Thereafter, the list will contain a new member and their tweets will be displayed there.
|
* Add to List: In order to see someone's tweets in one or more of your lists, you must add them first. In the dialogue box that opens after selecting the user, you will be asked to select the list you wish to add the user to. Thereafter, the list will contain a new member and their tweets will be displayed there.
|
||||||
* Remove from list: lets you remove a user from a list.
|
* Remove from list: lets you remove a user from a list.
|
||||||
* View lists: Shows the lists created by a specified user.
|
* View lists: Shows the lists created by a specified user.
|
||||||
@@ -153,8 +155,12 @@ Visually, Towards the top of the main application window, can be found a menu ba
|
|||||||
|
|
||||||
##### Buffer menu
|
##### Buffer menu
|
||||||
|
|
||||||
|
* Update buffer: Retrieves the newest items for the focused buffer. Normally, every buffer gets updated every couple of minutes, however you can force a specific buffer to be updated inmediately. Take into account, however, that the usage of this option repeatedly might exceed your allowed Twitter's API usage, in which case you would have to wait until it gets reset, tipycally within the next 15 minutes.
|
||||||
* New trending topics buffer: This opens a buffer to get the worlwide trending topics or those of a country or a city. You'll be able to select from a dialogue box if you wish to retrieve countries' trends, cities' trends or worldwide trends (this option is in the cities' list) and choose one from the selected list. The trending topics buffer will be created once the "OK" button has been activated within the dialogue box. Remember this kind of buffer will be updated every five minutes.
|
* New trending topics buffer: This opens a buffer to get the worlwide trending topics or those of a country or a city. You'll be able to select from a dialogue box if you wish to retrieve countries' trends, cities' trends or worldwide trends (this option is in the cities' list) and choose one from the selected list. The trending topics buffer will be created once the "OK" button has been activated within the dialogue box. Remember this kind of buffer will be updated every five minutes.
|
||||||
* Load previous items: This allows more items to be loaded for the specified buffer.
|
* Load previous items: This allows more items to be loaded for the specified buffer.
|
||||||
|
* Create filter: Creates a filter in the current buffer. Filters allow loading or ignoring tweets that meet certain conditions into a buffer. You can, for example, set a filter in the "home" buffer that loads tweets that are in English language only. By default, the filter creation dialog will place the focus on the field to name the filter. Currently, you can filter by word, by language, or both. In the filter by word, you can make TWBlue allow or ignore tweets with the desired word. In the filter by language, you can make the program load tweets in the languages you want, or ignore tweets written in certain languages. Once created, every filter will be saved in the session config and will be kept across application restarts.
|
||||||
|
* Manage filters: Opens up a dialogue which allows you to delete filters for the current session.
|
||||||
|
* Find a string in the currently focused buffer: Opens a dialogue where you can search for items in the current buffer.
|
||||||
* Mute: Mutes notifications of a particular buffer so you will not hear when new tweets arrive.
|
* Mute: Mutes notifications of a particular buffer so you will not hear when new tweets arrive.
|
||||||
* autoread: When enabled, the screen reader or SAPI 5 Text to Speech voice (if enabled) will read the text of incoming tweets. Please note that this could get rather chatty if there are a lot of incoming tweets.
|
* autoread: When enabled, the screen reader or SAPI 5 Text to Speech voice (if enabled) will read the text of incoming tweets. Please note that this could get rather chatty if there are a lot of incoming tweets.
|
||||||
* Clear buffer: Deletes all items from the buffer.
|
* Clear buffer: Deletes all items from the buffer.
|
||||||
@@ -173,6 +179,8 @@ Visually, Towards the top of the main application window, can be found a menu ba
|
|||||||
* What's new in this version?: opens up a document with the list of changes from the current version to the earliest.
|
* What's new in this version?: opens up a document with the list of changes from the current version to the earliest.
|
||||||
* Check for updates: every time you open the program it automatically checks for new versions. If an update is available, it will ask you if you want to download the update. If you accept, the updating process will commence. When complete, TWBlue will be restarted. This item checks for new updates without having to restart the application.
|
* Check for updates: every time you open the program it automatically checks for new versions. If an update is available, it will ask you if you want to download the update. If you accept, the updating process will commence. When complete, TWBlue will be restarted. This item checks for new updates without having to restart the application.
|
||||||
* TWBlue's website: visit our [home page](http://twblue.es) where you can find all relevant information and downloads for TWBlue and become a part of the community.
|
* TWBlue's website: visit our [home page](http://twblue.es) where you can find all relevant information and downloads for TWBlue and become a part of the community.
|
||||||
|
* Get soundpacks for TWBlue:
|
||||||
|
* Make a Donation: Opens a website from which you can donate to the TWBlue project. Donations are made through paypal and you don't need an account to donate.
|
||||||
* About TWBlue: shows the credits of the program.
|
* About TWBlue: shows the credits of the program.
|
||||||
|
|
||||||
### The invisible user interface
|
### The invisible user interface
|
||||||
@@ -350,4 +358,4 @@ Many thanks also to the people who worked on the documentation. Initially, [Manu
|
|||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright © 2013-2017. Manuel Cortéz
|
Copyright © 2013-2021. Manuel Cortéz
|
@@ -5,19 +5,6 @@ return "key\0";
|
|||||||
char *get_api_secret(){
|
char *get_api_secret(){
|
||||||
return "secret_key\0";
|
return "secret_key\0";
|
||||||
}
|
}
|
||||||
char *get_dropbox_api_key(){
|
|
||||||
return "key\0";
|
|
||||||
}
|
|
||||||
char *get_dropbox_api_secret(){
|
|
||||||
return "secret_key\0";
|
|
||||||
}
|
|
||||||
char *get_twishort_api_key(){
|
char *get_twishort_api_key(){
|
||||||
return "key\0";
|
return "key\0";
|
||||||
}
|
}
|
||||||
char *get_bts_user(){
|
|
||||||
return "user\0";
|
|
||||||
}
|
|
||||||
char *get_bts_password(){
|
|
||||||
return "pass\0";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@@ -3,10 +3,6 @@
|
|||||||
|
|
||||||
char *get_api_key();
|
char *get_api_key();
|
||||||
char *get_api_secret();
|
char *get_api_secret();
|
||||||
char *get_dropbox_api_key();
|
|
||||||
char *get_dropbox_api_secret();
|
|
||||||
char *get_twishort_api_key();
|
char *get_twishort_api_key();
|
||||||
char *get_bts_user();
|
|
||||||
char *get_bts_password();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
wxpython
|
wxpython
|
||||||
|
pytest
|
||||||
|
coverage
|
||||||
wheel
|
wheel
|
||||||
six
|
future
|
||||||
configobj
|
configobj
|
||||||
markdown
|
markdown
|
||||||
future
|
|
||||||
requests
|
requests
|
||||||
oauthlib
|
oauthlib
|
||||||
requests-oauthlib
|
requests-oauthlib
|
||||||
requests-toolbelt
|
requests-toolbelt
|
||||||
pypubsub
|
pypubsub
|
||||||
pygeocoder
|
geopy
|
||||||
arrow
|
arrow
|
||||||
python-dateutil
|
python-dateutil
|
||||||
futures
|
|
||||||
winpaths
|
winpaths
|
||||||
PySocks
|
PySocks
|
||||||
win_inet_pton
|
win_inet_pton
|
||||||
@@ -25,13 +25,31 @@ urllib3
|
|||||||
youtube-dl
|
youtube-dl
|
||||||
python-vlc
|
python-vlc
|
||||||
pypiwin32
|
pypiwin32
|
||||||
|
pywin32
|
||||||
certifi
|
certifi
|
||||||
backports.functools_lru_cache
|
backports.functools_lru_cache
|
||||||
cx_freeze
|
cx_freeze
|
||||||
tweepy
|
tweepy
|
||||||
twitter-text-parser
|
twitter-text-parser
|
||||||
|
mastodon.py
|
||||||
pyenchant
|
pyenchant
|
||||||
sqlitedict
|
sqlitedict
|
||||||
|
cx-Logging
|
||||||
|
h11
|
||||||
|
h2
|
||||||
|
hpack
|
||||||
|
hstspreload
|
||||||
|
httpcore
|
||||||
|
httpx
|
||||||
|
hyperframe
|
||||||
|
rfc3986
|
||||||
|
sniffio
|
||||||
|
attrs
|
||||||
|
importlib-metadata
|
||||||
|
numpy
|
||||||
|
pillow
|
||||||
|
charset-normalizer
|
||||||
|
demoji
|
||||||
git+https://github.com/accessibleapps/libloader
|
git+https://github.com/accessibleapps/libloader
|
||||||
git+https://github.com/accessibleapps/platform_utils
|
git+https://github.com/accessibleapps/platform_utils
|
||||||
git+https://github.com/accessibleapps/accessible_output2
|
git+https://github.com/accessibleapps/accessible_output2
|
||||||
|
@@ -14,11 +14,11 @@ SetCompress auto
|
|||||||
SetCompressor /solid lzma
|
SetCompressor /solid lzma
|
||||||
SetDatablockOptimize on
|
SetDatablockOptimize on
|
||||||
VIAddVersionKey ProductName "TWBlue"
|
VIAddVersionKey ProductName "TWBlue"
|
||||||
VIAddVersionKey LegalCopyright "Copyright 2014-2021 Manuel Cortéz."
|
VIAddVersionKey LegalCopyright "Copyright 2014-2022 MCV Software."
|
||||||
VIAddVersionKey ProductVersion "0.95"
|
VIAddVersionKey ProductVersion "0.95.0"
|
||||||
VIAddVersionKey FileVersion "0.95"
|
VIAddVersionKey FileVersion "0.95.0"
|
||||||
VIProductVersion "0.95.0.0"
|
VIProductVersion "0.95.0"
|
||||||
VIFileVersion "0.95.0.0"
|
VIFileVersion "0.95.0"
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
||||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||||
@@ -32,7 +32,7 @@ var StartMenuFolder
|
|||||||
!insertmacro MUI_PAGE_FINISH
|
!insertmacro MUI_PAGE_FINISH
|
||||||
!insertmacro MUI_UNPAGE_CONFIRM
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
!insertmacro MUI_UNPAGE_INSTFILES
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
!insertmacro MUI_LANGUAGE "English"
|
!insertmacro MUI_LANGUAGE "English"
|
||||||
!insertmacro MUI_LANGUAGE "French"
|
!insertmacro MUI_LANGUAGE "French"
|
||||||
!insertmacro MUI_LANGUAGE "Spanish"
|
!insertmacro MUI_LANGUAGE "Spanish"
|
||||||
!insertmacro MUI_LANGUAGE "Italian"
|
!insertmacro MUI_LANGUAGE "Italian"
|
||||||
@@ -73,9 +73,9 @@ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "U
|
|||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortéz"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortéz"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.95"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.95"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.es"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "https://twblue.es"
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 95
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 0
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
@@ -1,95 +0,0 @@
|
|||||||
!include "MUI2.nsh"
|
|
||||||
!include "LogicLib.nsh"
|
|
||||||
!include "x64.nsh"
|
|
||||||
Unicode true
|
|
||||||
CRCCheck on
|
|
||||||
ManifestSupportedOS all
|
|
||||||
XPStyle on
|
|
||||||
Name "TWBlue"
|
|
||||||
OutFile "TWBlue_snapshot_setup.exe"
|
|
||||||
InstallDir "$PROGRAMFILES\twblue"
|
|
||||||
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "InstallLocation"
|
|
||||||
RequestExecutionLevel admin
|
|
||||||
SetCompress auto
|
|
||||||
SetCompressor /solid lzma
|
|
||||||
SetDatablockOptimize on
|
|
||||||
VIAddVersionKey ProductName "TWBlue Snapshot version"
|
|
||||||
VIAddVersionKey LegalCopyright "Copyright 2014-2021 Manuel Cortéz."
|
|
||||||
VIAddVersionKey ProductVersion "9"
|
|
||||||
VIAddVersionKey FileVersion "9"
|
|
||||||
VIProductVersion "9.0.0.0"
|
|
||||||
VIFileVersion "9.0.0.0"
|
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
|
||||||
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
|
||||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
|
||||||
!insertmacro MUI_PAGE_DIRECTORY
|
|
||||||
var StartMenuFolder
|
|
||||||
!insertmacro MUI_PAGE_STARTMENU startmenu $StartMenuFolder
|
|
||||||
!insertmacro MUI_PAGE_INSTFILES
|
|
||||||
!define MUI_FINISHPAGE_LINK "Visit TWBlue website"
|
|
||||||
!define MUI_FINISHPAGE_LINK_LOCATION "https://twblue.es"
|
|
||||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\TWBlue.exe"
|
|
||||||
!insertmacro MUI_PAGE_FINISH
|
|
||||||
!insertmacro MUI_UNPAGE_CONFIRM
|
|
||||||
!insertmacro MUI_UNPAGE_INSTFILES
|
|
||||||
!insertmacro MUI_LANGUAGE "English"
|
|
||||||
!insertmacro MUI_LANGUAGE "French"
|
|
||||||
!insertmacro MUI_LANGUAGE "Spanish"
|
|
||||||
!insertmacro MUI_LANGUAGE "Italian"
|
|
||||||
!insertmacro MUI_LANGUAGE "Finnish"
|
|
||||||
!insertmacro MUI_LANGUAGE "Russian"
|
|
||||||
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
|
||||||
!insertmacro MUI_LANGUAGE "Polish"
|
|
||||||
!insertmacro MUI_LANGUAGE "German"
|
|
||||||
!insertmacro MUI_LANGUAGE "Hungarian"
|
|
||||||
!insertmacro MUI_LANGUAGE "Turkish"
|
|
||||||
!insertmacro MUI_LANGUAGE "Arabic"
|
|
||||||
!insertmacro MUI_LANGUAGE "Galician"
|
|
||||||
!insertmacro MUI_LANGUAGE "Catalan"
|
|
||||||
!insertmacro MUI_LANGUAGE "Basque"
|
|
||||||
!insertmacro MUI_LANGUAGE "Croatian"
|
|
||||||
!insertmacro MUI_LANGUAGE "Japanese"
|
|
||||||
!insertmacro MUI_LANGUAGE "SerbianLatin"
|
|
||||||
!insertmacro MUI_LANGUAGE "Romanian"
|
|
||||||
!insertmacro MUI_RESERVEFILE_LANGDLL
|
|
||||||
Section
|
|
||||||
SetShellVarContext All
|
|
||||||
SetOutPath "$INSTDIR"
|
|
||||||
${If} ${RunningX64}
|
|
||||||
File /r TWBlue64\*
|
|
||||||
${Else}
|
|
||||||
File /r TWBlue\*
|
|
||||||
${EndIf}
|
|
||||||
CreateShortCut "$DESKTOP\TWBlue.lnk" "$INSTDIR\TWBlue.exe"
|
|
||||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN startmenu
|
|
||||||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
|
||||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TWBlue.lnk" "$INSTDIR\TWBlue.exe"
|
|
||||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TWBlue on the web.lnk" "http://twblue.es"
|
|
||||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
|
||||||
!insertmacro MUI_STARTMENU_WRITE_END
|
|
||||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayName" "TWBlue"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortéz"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "9"
|
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "https://twblue.es"
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 0
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
|
||||||
SectionEnd
|
|
||||||
Section "Uninstall"
|
|
||||||
SetShellVarContext All
|
|
||||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue"
|
|
||||||
RMDir /r /REBOOTOK $INSTDIR
|
|
||||||
Delete "$DESKTOP\TWBlue.lnk"
|
|
||||||
!insertmacro MUI_STARTMENU_GETFOLDER startmenu $StartMenuFolder
|
|
||||||
RMDir /r "$SMPROGRAMS\$StartMenuFolder"
|
|
||||||
SectionEnd
|
|
||||||
Function .onInit
|
|
||||||
${If} ${RunningX64}
|
|
||||||
StrCpy $instdir "$programfiles64\twblue"
|
|
||||||
${EndIf}
|
|
||||||
!insertmacro MUI_LANGDLL_DISPLAY
|
|
||||||
FunctionEnd
|
|
@@ -14,14 +14,15 @@ retweet_mode = string(default="ask")
|
|||||||
persist_size = integer(default=0)
|
persist_size = integer(default=0)
|
||||||
load_cache_in_memory=boolean(default=True)
|
load_cache_in_memory=boolean(default=True)
|
||||||
show_screen_names = boolean(default=False)
|
show_screen_names = boolean(default=False)
|
||||||
buffer_order = list(default=list('home','mentions', 'dm', 'sent_dm', 'sent_tweets','favorites','followers','friends','blocks','muted','events'))
|
hide_emojis = boolean(default=False)
|
||||||
|
buffer_order = list(default=list('home','mentions', 'dm', 'sent_dm', 'sent_tweets','favorites','followers','friends','blocks','muted'))
|
||||||
|
|
||||||
[sound]
|
[sound]
|
||||||
volume = float(default=1.0)
|
volume = float(default=1.0)
|
||||||
input_device = string(default="Default")
|
input_device = string(default="Default")
|
||||||
output_device = string(default="Default")
|
output_device = string(default="Default")
|
||||||
session_mute = boolean(default=False)
|
session_mute = boolean(default=False)
|
||||||
current_soundpack = string(default="default")
|
current_soundpack = string(default="FreakyBlue")
|
||||||
indicate_audio = boolean(default=True)
|
indicate_audio = boolean(default=True)
|
||||||
indicate_geo = boolean(default=True)
|
indicate_geo = boolean(default=True)
|
||||||
indicate_img = boolean(default=True)
|
indicate_img = boolean(default=True)
|
||||||
@@ -48,4 +49,12 @@ ocr_language = string(default="")
|
|||||||
braille_reporting = boolean(default=True)
|
braille_reporting = boolean(default=True)
|
||||||
speech_reporting = boolean(default=True)
|
speech_reporting = boolean(default=True)
|
||||||
|
|
||||||
|
[templates]
|
||||||
|
tweet = string(default="$display_name, $text $image_descriptions $date. $source")
|
||||||
|
dm = string(default="$sender_display_name, $text $date")
|
||||||
|
dm_sent = string(default="Dm to $recipient_display_name, $text $date")
|
||||||
|
person = string(default="$display_name (@$screen_name). $followers followers, $following following, $tweets tweets. Joined Twitter $created_at.")
|
||||||
|
|
||||||
[filters]
|
[filters]
|
||||||
|
|
||||||
|
[user-aliases]
|
@@ -1,22 +1,14 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import datetime
|
|
||||||
|
|
||||||
name = 'TWBlue'
|
name = 'TWBlue'
|
||||||
short_name='twblue'
|
short_name='twblue'
|
||||||
snapshot = True
|
update_url = 'https://twblue.es/updates/updates.php'
|
||||||
if snapshot == False:
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/updates.json'
|
||||||
version = "0.95"
|
|
||||||
update_url = 'https://twblue.es/updates/stable.php'
|
|
||||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
|
||||||
else:
|
|
||||||
version = "9"
|
|
||||||
update_url = 'https://twblue.es/updates/snapshot.php'
|
|
||||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
|
||||||
authors = ["Manuel Cortéz", "José Manuel Delicado"]
|
authors = ["Manuel Cortéz", "José Manuel Delicado"]
|
||||||
authorEmail = "manuel@manuelcortez.net"
|
authorEmail = "manuel@manuelcortez.net"
|
||||||
copyright = "Copyright (C) 2013-2021, Manuel cortéz."
|
copyright = "Copyright (C) 2013-2022, MCV Software."
|
||||||
description = name+" is an app designed to use Twitter simply and efficiently while using minimal system resources. This app provides access to most Twitter features."
|
description = name+" is an app designed to use Twitter simply and efficiently while using minimal system resources. This app provides access to most Twitter features."
|
||||||
translators = ["Manuel Cortéz (English)", "Mohammed Al Shara, Hatoun Felemban (Arabic)", "Francisco Torres (Catalan)", "Manuel cortéz (Spanish)", "Sukil Etxenike Arizaleta (Basque)", "Jani Kinnunen (finnish)", "Oreonan (Français)", "Juan Buño (Galician)", "Steffen Schultz (German)", "Zvonimir Stanečić (Croatian)", "Robert Osztolykan (Hungarian)", "Christian Leo Mameli (Italian)", "Riku (Japanese)", "Paweł Masarczyk (Polish)", "Odenilton Júnior Santos (Portuguese)", "Florian Ionașcu, Nicușor Untilă (Romanian)", "Natalia Hedlund, Valeria Kuznetsova (Russian)", "Aleksandar Đurić (Serbian)", "Burak Yüksek (Turkish)"]
|
translators = ["Manuel Cortéz (English)", "Mohammed Al Shara, Hatoun Felemban (Arabic)", "Francisco Torres (Catalan)", "Manuel cortéz (Spanish)", "Sukil Etxenike Arizaleta (Basque)", "Jani Kinnunen (finnish)", "Corentin Bacqué-Cazenave (Français)", "Juan Buño (Galician)", "Steffen Schultz (German)", "Zvonimir Stanečić (Croatian)", "Robert Osztolykan (Hungarian)", "Christian Leo Mameli (Italian)", "Riku (Japanese)", "Paweł Masarczyk (Polish)", "Odenilton Júnior Santos (Portuguese)", "Florian Ionașcu, Nicușor Untilă (Romanian)", "Natalia Hedlund, Valeria Kuznetsova (Russian)", "Aleksandar Đurić (Serbian)", "Burak Yüksek (Turkish)"]
|
||||||
url = u"https://twblue.es"
|
url = "https://twblue.es"
|
||||||
report_bugs_url = "https://github.com/manuelcortez/twblue/issues"
|
report_bugs_url = "https://github.com/mcvsoftware/twblue/issues"
|
||||||
supported_languages = []
|
supported_languages = []
|
||||||
|
version = "11"
|
||||||
|
@@ -4,6 +4,7 @@ from validate import Validator, ValidateError
|
|||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
from wxUI import commonMessageDialogs
|
||||||
log = getLogger("config_utils")
|
log = getLogger("config_utils")
|
||||||
|
|
||||||
class ConfigLoadError(Exception): pass
|
class ConfigLoadError(Exception): pass
|
||||||
@@ -21,6 +22,7 @@ def load_config(config_path, configspec_path=None, copy=True, *args, **kwargs):
|
|||||||
return config
|
return config
|
||||||
else:
|
else:
|
||||||
log.exception("Error in config file: {0}".format(validated,))
|
log.exception("Error in config file: {0}".format(validated,))
|
||||||
|
commonMessageDialogs.invalid_configuration()
|
||||||
|
|
||||||
def is_blank(arg):
|
def is_blank(arg):
|
||||||
"Check if a line is blank."
|
"Check if a line is blank."
|
||||||
|
@@ -1,40 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
from builtins import object
|
|
||||||
import os
|
|
||||||
import widgetUtils
|
|
||||||
import logging
|
|
||||||
from wxUI.dialogs import attach as gui
|
|
||||||
log = logging.getLogger("controller.attach")
|
|
||||||
|
|
||||||
class attach(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.attachments = list()
|
|
||||||
self.dialog = gui.attachDialog()
|
|
||||||
widgetUtils.connect_event(self.dialog.photo, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
|
||||||
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_attachment)
|
|
||||||
self.dialog.get_response()
|
|
||||||
log.debug("Attachments controller started.")
|
|
||||||
|
|
||||||
def upload_image(self, *args, **kwargs):
|
|
||||||
image, description = self.dialog.get_image()
|
|
||||||
if image != None:
|
|
||||||
imageInfo = {"type": "photo", "file": image, "description": description}
|
|
||||||
log.debug("Image data to upload: %r" % (imageInfo,))
|
|
||||||
self.attachments.append(imageInfo)
|
|
||||||
info = [_(u"Photo"), description]
|
|
||||||
self.dialog.attachments.insert_item(False, *info)
|
|
||||||
self.dialog.remove.Enable(True)
|
|
||||||
|
|
||||||
def remove_attachment(self, *args, **kwargs):
|
|
||||||
current_item = self.dialog.attachments.get_selected()
|
|
||||||
log.debug("Removing item %d" % (current_item,))
|
|
||||||
if current_item == -1: current_item = 0
|
|
||||||
self.attachments.pop(current_item)
|
|
||||||
self.dialog.attachments.remove_item(current_item)
|
|
||||||
self.check_remove_status()
|
|
||||||
log.debug("Removed")
|
|
||||||
|
|
||||||
def check_remove_status(self):
|
|
||||||
if len(self.attachments) == 0 and self.dialog.attachments.get_count() == 0:
|
|
||||||
self.dialog.remove.Enable(False)
|
|
@@ -1,3 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from . import base as base
|
from . import base as base
|
||||||
from . import twitter as twitter
|
from . import twitter as twitter
|
||||||
|
from . import mastodon as mastodon
|
@@ -125,6 +125,9 @@ class Buffer(object):
|
|||||||
def share_item(self):
|
def share_item(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def can_share(self):
|
||||||
|
pass
|
||||||
|
|
||||||
def destroy_status(self):
|
def destroy_status(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -135,4 +138,7 @@ class Buffer(object):
|
|||||||
try:
|
try:
|
||||||
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def view_item(self):
|
||||||
|
pass
|
5
src/controller/buffers/mastodon/__init__.py
Normal file
5
src/controller/buffers/mastodon/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from .base import BaseBuffer
|
||||||
|
from .mentions import MentionsBuffer
|
||||||
|
from .conversations import ConversationBuffer, ConversationListBuffer
|
||||||
|
from .users import UserBuffer
|
498
src/controller/buffers/mastodon/base.py
Normal file
498
src/controller/buffers/mastodon/base.py
Normal file
@@ -0,0 +1,498 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import time
|
||||||
|
import wx
|
||||||
|
import widgetUtils
|
||||||
|
import arrow
|
||||||
|
import webbrowser
|
||||||
|
import output
|
||||||
|
import config
|
||||||
|
import sound
|
||||||
|
import languageHandler
|
||||||
|
import logging
|
||||||
|
from audio_services import youtube_utils
|
||||||
|
from controller.buffers.base import base
|
||||||
|
from controller.mastodon import messages
|
||||||
|
from sessions.mastodon import compose, utils, templates
|
||||||
|
from mysc.thread_utils import call_threaded
|
||||||
|
from pubsub import pub
|
||||||
|
from extra import ocr
|
||||||
|
from wxUI import buffers, dialogs, commonMessageDialogs
|
||||||
|
from wxUI.dialogs.mastodon import menus
|
||||||
|
from wxUI.dialogs.mastodon import dialogs as mastodon_dialogs
|
||||||
|
|
||||||
|
log = logging.getLogger("controller.buffers.mastodon.base")
|
||||||
|
|
||||||
|
class BaseBuffer(base.Buffer):
|
||||||
|
def __init__(self, parent, function, name, sessionObject, account, sound=None, compose_func="compose_post", *args, **kwargs):
|
||||||
|
super(BaseBuffer, self).__init__(parent, function, *args, **kwargs)
|
||||||
|
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||||
|
self.create_buffer(parent, name)
|
||||||
|
self.invisible = True
|
||||||
|
self.name = name
|
||||||
|
self.type = self.buffer.type
|
||||||
|
self.session = sessionObject
|
||||||
|
self.compose_function = getattr(compose, compose_func)
|
||||||
|
log.debug("Compose_function: %s" % (self.compose_function,))
|
||||||
|
self.account = account
|
||||||
|
self.buffer.account = account
|
||||||
|
self.bind_events()
|
||||||
|
self.sound = sound
|
||||||
|
if "-timeline" in self.name or "-followers" in self.name or "-following" in self.name:
|
||||||
|
self.finished_timeline = False
|
||||||
|
|
||||||
|
def create_buffer(self, parent, name):
|
||||||
|
self.buffer = buffers.mastodon.basePanel(parent, name)
|
||||||
|
|
||||||
|
def get_buffer_name(self):
|
||||||
|
""" Get buffer name from a set of different techniques."""
|
||||||
|
# firstly let's take the easier buffers.
|
||||||
|
basic_buffers = dict(home_timeline=_("Home"), local_timeline=_("Local"), federated_timeline=_("Federated"), mentions=_("Mentions"), bookmarks=_("Bookmarks"), direct_messages=_("Direct messages"), sent=_("Sent"), favorites=_("Favorites"), followers=_("Followers"), following=_("Following"), blocked=_("Blocked users"), muted=_("Muted users"), notifications=_("Notifications"))
|
||||||
|
if self.name in list(basic_buffers.keys()):
|
||||||
|
return basic_buffers[self.name]
|
||||||
|
# Check user timelines
|
||||||
|
elif hasattr(self, "username"):
|
||||||
|
if "-timeline" in self.name:
|
||||||
|
return _(u"{username}'s timeline").format(username=self.username,)
|
||||||
|
elif "-followers" in self.name:
|
||||||
|
return _(u"{username}'s followers").format(username=self.username,)
|
||||||
|
elif "-following" in self.name:
|
||||||
|
return _(u"{username}'s following").format(username=self.username,)
|
||||||
|
log.error("Error getting name for buffer %s" % (self.name,))
|
||||||
|
return _(u"Unknown buffer")
|
||||||
|
|
||||||
|
def post_status(self, *args, **kwargs):
|
||||||
|
title = _("Post")
|
||||||
|
caption = _("Write your post here")
|
||||||
|
post = messages.post(session=self.session, title=title, caption=caption)
|
||||||
|
response = post.message.ShowModal()
|
||||||
|
if response == wx.ID_OK:
|
||||||
|
post_data = post.get_data()
|
||||||
|
call_threaded(self.session.send_post, posts=post_data, visibility=post.get_visibility(), **kwargs)
|
||||||
|
if hasattr(post.message, "destroy"):
|
||||||
|
post.message.destroy()
|
||||||
|
|
||||||
|
def get_formatted_message(self):
|
||||||
|
return self.compose_function(self.get_item(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])[1]
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
post = self.get_item()
|
||||||
|
if post == None:
|
||||||
|
return
|
||||||
|
template = self.session.settings["templates"]["post"]
|
||||||
|
|
||||||
|
t = templates.render_post(post, template, relative_times=self.session.settings["general"]["relative_times"], offset_hours=self.session.db["utc_offset"])
|
||||||
|
return t
|
||||||
|
|
||||||
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
|
current_time = time.time()
|
||||||
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
|
self.execution_time = current_time
|
||||||
|
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||||
|
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||||
|
count = self.session.settings["general"]["max_posts_per_call"]
|
||||||
|
min_id = None
|
||||||
|
# toDo: Implement reverse timelines properly here.
|
||||||
|
if (self.name != "favorites" and self.name != "bookmarks") and self.name in self.session.db and len(self.session.db[self.name]) > 0:
|
||||||
|
min_id = self.session.db[self.name][-1].id
|
||||||
|
try:
|
||||||
|
results = getattr(self.session.api, self.function)(min_id=min_id, limit=count, *self.args, **self.kwargs)
|
||||||
|
results.reverse()
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
number_of_items = self.session.order_buffer(self.name, results)
|
||||||
|
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||||
|
if hasattr(self, "finished_timeline") and self.finished_timeline == False:
|
||||||
|
if "-timeline" in self.name:
|
||||||
|
self.username = self.session.db[self.name][0]["account"].username
|
||||||
|
self.finished_timeline = True
|
||||||
|
self.put_items_on_list(number_of_items)
|
||||||
|
if number_of_items > 0 and self.name != "sent_posts" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(number_of_items)
|
||||||
|
return number_of_items
|
||||||
|
|
||||||
|
def auto_read(self, number_of_items):
|
||||||
|
if number_of_items == 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
post = self.session.db[self.name][-1]
|
||||||
|
else:
|
||||||
|
post = self.session.db[self.name][0]
|
||||||
|
output.speak(_("New post in {0}").format(self.get_buffer_name()))
|
||||||
|
output.speak(" ".join(self.compose_function(post, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])))
|
||||||
|
elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
output.speak(_("{0} new posts in {1}.").format(number_of_items, self.get_buffer_name()))
|
||||||
|
|
||||||
|
def get_more_items(self):
|
||||||
|
elements = []
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
max_id = self.session.db[self.name][0].id
|
||||||
|
else:
|
||||||
|
max_id = self.session.db[self.name][-1].id
|
||||||
|
try:
|
||||||
|
items = getattr(self.session.api, self.function)(max_id=max_id, limit=self.session.settings["general"]["max_posts_per_call"], *self.args, **self.kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
items_db = self.session.db[self.name]
|
||||||
|
for i in items:
|
||||||
|
if utils.find_item(i, self.session.db[self.name]) == None:
|
||||||
|
elements.append(i)
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
items_db.insert(0, i)
|
||||||
|
else:
|
||||||
|
items_db.append(i)
|
||||||
|
self.session.db[self.name] = items_db
|
||||||
|
selection = self.buffer.list.get_selected()
|
||||||
|
log.debug("Retrieved %d items from cursored search in function %s." % (len(elements), self.function))
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
for i in elements:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(True, *post)
|
||||||
|
else:
|
||||||
|
for i in items:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(False, *post)
|
||||||
|
self.buffer.list.select_item(selection)
|
||||||
|
output.speak(_(u"%s items retrieved") % (str(len(elements))), True)
|
||||||
|
|
||||||
|
def remove_buffer(self, force=False):
|
||||||
|
if "-timeline" in self.name:
|
||||||
|
if force == False:
|
||||||
|
dlg = commonMessageDialogs.remove_buffer()
|
||||||
|
else:
|
||||||
|
dlg = widgetUtils.YES
|
||||||
|
if dlg == widgetUtils.YES:
|
||||||
|
if self.kwargs.get("id") in self.session.settings["other_buffers"]["timelines"]:
|
||||||
|
self.session.settings["other_buffers"]["timelines"].remove(self.kwargs.get("id"))
|
||||||
|
self.session.settings.write()
|
||||||
|
if self.name in self.session.db:
|
||||||
|
self.session.db.pop(self.name)
|
||||||
|
return True
|
||||||
|
elif dlg == widgetUtils.NO:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def put_items_on_list(self, number_of_items):
|
||||||
|
list_to_use = self.session.db[self.name]
|
||||||
|
if number_of_items == 0 and self.session.settings["general"]["persist_size"] == 0: return
|
||||||
|
log.debug("The list contains %d items " % (self.buffer.list.get_count(),))
|
||||||
|
log.debug("Putting %d items on the list" % (number_of_items,))
|
||||||
|
if self.buffer.list.get_count() == 0:
|
||||||
|
for i in list_to_use:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(False, *post)
|
||||||
|
self.buffer.set_position(self.session.settings["general"]["reverse_timelines"])
|
||||||
|
elif self.buffer.list.get_count() > 0 and number_of_items > 0:
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
items = list_to_use[len(list_to_use)-number_of_items:]
|
||||||
|
for i in items:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(False, *post)
|
||||||
|
else:
|
||||||
|
items = list_to_use[0:number_of_items]
|
||||||
|
items.reverse()
|
||||||
|
for i in items:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(True, *post)
|
||||||
|
log.debug("Now the list contains %d items " % (self.buffer.list.get_count(),))
|
||||||
|
|
||||||
|
def add_new_item(self, item):
|
||||||
|
post = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
self.buffer.list.insert_item(False, *post)
|
||||||
|
else:
|
||||||
|
self.buffer.list.insert_item(True, *post)
|
||||||
|
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
output.speak(" ".join(post[:2]), speech=self.session.settings["reporting"]["speech_reporting"], braille=self.session.settings["reporting"]["braille_reporting"])
|
||||||
|
|
||||||
|
def update_item(self, item, position):
|
||||||
|
post = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.list.SetItem(position, 1, post[1])
|
||||||
|
|
||||||
|
def bind_events(self):
|
||||||
|
log.debug("Binding events...")
|
||||||
|
self.buffer.set_focus_function(self.onFocus)
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, widgetUtils.KEYPRESS, self.get_event)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_status, self.buffer.post)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.share_item, self.buffer.boost)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.send_message, self.buffer.dm)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.toggle_favorite, self.buffer.fav)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.toggle_bookmark, self.buffer.bookmark)
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
||||||
|
|
||||||
|
def show_menu(self, ev, pos=0, *args, **kwargs):
|
||||||
|
if self.buffer.list.get_count() == 0:
|
||||||
|
return
|
||||||
|
menu = menus.base()
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.reply, menuitem=menu.reply)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.share_item, menuitem=menu.boost)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.fav, menuitem=menu.fav)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.unfav, menuitem=menu.unfav)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.url_, menuitem=menu.openUrl)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.audio, menuitem=menu.play)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove)
|
||||||
|
if hasattr(menu, "openInBrowser"):
|
||||||
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.open_in_browser, menuitem=menu.openInBrowser)
|
||||||
|
if pos != 0:
|
||||||
|
self.buffer.PopupMenu(menu, pos)
|
||||||
|
else:
|
||||||
|
self.buffer.PopupMenu(menu, self.buffer.list.list.GetPosition())
|
||||||
|
|
||||||
|
def view(self, *args, **kwargs):
|
||||||
|
pub.sendMessage("execute-action", action="view_item")
|
||||||
|
|
||||||
|
def copy(self, *args, **kwargs):
|
||||||
|
pub.sendMessage("execute-action", action="copy_to_clipboard")
|
||||||
|
|
||||||
|
def user_actions(self, *args, **kwargs):
|
||||||
|
pub.sendMessage("execute-action", action="follow")
|
||||||
|
|
||||||
|
def fav(self, *args, **kwargs):
|
||||||
|
pub.sendMessage("execute-action", action="add_to_favourites")
|
||||||
|
|
||||||
|
def unfav(self, *args, **kwargs):
|
||||||
|
pub.sendMessage("execute-action", action="remove_from_favourites")
|
||||||
|
|
||||||
|
def delete_item_(self, *args, **kwargs):
|
||||||
|
pub.sendMessage("execute-action", action="delete_item")
|
||||||
|
|
||||||
|
def url_(self, *args, **kwargs):
|
||||||
|
self.url()
|
||||||
|
|
||||||
|
def show_menu_by_key(self, ev):
|
||||||
|
if self.buffer.list.get_count() == 0:
|
||||||
|
return
|
||||||
|
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||||
|
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
||||||
|
|
||||||
|
def get_item(self):
|
||||||
|
index = self.buffer.list.get_selected()
|
||||||
|
if index > -1 and self.session.db.get(self.name) != None:
|
||||||
|
return self.session.db[self.name][index]
|
||||||
|
|
||||||
|
def can_share(self):
|
||||||
|
post = self.get_item()
|
||||||
|
if post.visibility == "direct":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def reply(self, *args):
|
||||||
|
item = self.get_item()
|
||||||
|
visibility = item.visibility
|
||||||
|
if visibility == "direct":
|
||||||
|
title = _("Conversation with {}").format(item.account.username)
|
||||||
|
caption = _("Write your message here")
|
||||||
|
else:
|
||||||
|
title = _("Reply to {}").format(item.account.username)
|
||||||
|
caption = _("Write your reply here")
|
||||||
|
if item.reblog != None:
|
||||||
|
users = ["@{} ".format(user.acct) for user in item.reblog.mentions if user.id != self.session.db["user_id"]]
|
||||||
|
if item.reblog.account.acct != item.account.acct and "@{} ".format(item.reblog.account.acct) not in users:
|
||||||
|
users.append("@{} ".format(item.reblog.account.acct))
|
||||||
|
else:
|
||||||
|
users = ["@{} ".format(user.acct) for user in item.mentions if user.id != self.session.db["user_id"]]
|
||||||
|
if "@{} ".format(item.account.acct) not in users and item.account.id != self.session.db["user_id"]:
|
||||||
|
users.insert(0, "@{} ".format(item.account.acct))
|
||||||
|
users_str = "".join(users)
|
||||||
|
post = messages.post(session=self.session, title=title, caption=caption, text=users_str)
|
||||||
|
visibility_settings = dict(public=0, unlisted=1, private=2, direct=3)
|
||||||
|
post.message.visibility.SetSelection(visibility_settings.get(visibility))
|
||||||
|
# Respect content warning settings.
|
||||||
|
if item.sensitive:
|
||||||
|
post.message.sensitive.SetValue(item.sensitive)
|
||||||
|
post.message.spoiler.ChangeValue(item.spoiler_text)
|
||||||
|
post.message.on_sensitivity_changed()
|
||||||
|
response = post.message.ShowModal()
|
||||||
|
if response == wx.ID_OK:
|
||||||
|
post_data = post.get_data()
|
||||||
|
call_threaded(self.session.send_post, reply_to=item.id, posts=post_data, visibility=post.get_visibility())
|
||||||
|
if hasattr(post.message, "destroy"):
|
||||||
|
post.message.destroy()
|
||||||
|
|
||||||
|
def send_message(self, *args, **kwargs):
|
||||||
|
item = self.get_item()
|
||||||
|
title = _("Conversation with {}").format(item.account.username)
|
||||||
|
caption = _("Write your message here")
|
||||||
|
if item.reblog != None:
|
||||||
|
users = ["@{} ".format(user.acct) for user in item.reblog.mentions if user.id != self.session.db["user_id"]]
|
||||||
|
if item.reblog.account.acct != item.account.acct and "@{} ".format(item.reblog.account.acct) not in users:
|
||||||
|
users.append("@{} ".format(item.reblog.account.acct))
|
||||||
|
else:
|
||||||
|
users = ["@{} ".format(user.acct) for user in item.mentions if user.id != self.session.db["user_id"]]
|
||||||
|
if item.account.acct not in users and item.account.id != self.session.db["user_id"]:
|
||||||
|
users.insert(0, "@{} ".format(item.account.acct))
|
||||||
|
users_str = "".join(users)
|
||||||
|
post = messages.post(session=self.session, title=title, caption=caption, text=users_str)
|
||||||
|
post.message.visibility.SetSelection(3)
|
||||||
|
if item.sensitive:
|
||||||
|
post.message.sensitive.SetValue(item.sensitive)
|
||||||
|
post.message.spoiler.ChangeValue(item.spoiler_text)
|
||||||
|
post.message.on_sensitivity_changed()
|
||||||
|
response = post.message.ShowModal()
|
||||||
|
if response == wx.ID_OK:
|
||||||
|
post_data = post.get_data()
|
||||||
|
call_threaded(self.session.send_post, posts=post_data, visibility="direct", reply_to=item.id)
|
||||||
|
if hasattr(post.message, "destroy"):
|
||||||
|
post.message.destroy()
|
||||||
|
|
||||||
|
def share_item(self, *args, **kwargs):
|
||||||
|
if self.can_share() == False:
|
||||||
|
return output.speak(_("This action is not supported on conversation posts."))
|
||||||
|
post = self.get_item()
|
||||||
|
id = post.id
|
||||||
|
if self.session.settings["general"]["boost_mode"] == "ask":
|
||||||
|
answer = mastodon_dialogs.boost_question()
|
||||||
|
if answer == True:
|
||||||
|
self._direct_boost(id)
|
||||||
|
else:
|
||||||
|
self._direct_boost(id)
|
||||||
|
|
||||||
|
def _direct_boost(self, id):
|
||||||
|
item = self.session.api_call(call_name="status_reblog", _sound="retweet_send.ogg", id=id)
|
||||||
|
|
||||||
|
def onFocus(self, *args, **kwargs):
|
||||||
|
post = self.get_item()
|
||||||
|
if self.session.settings["general"]["relative_times"] == True:
|
||||||
|
original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()].created_at)
|
||||||
|
ts = original_date.humanize(locale=languageHandler.getLanguage())
|
||||||
|
self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, ts)
|
||||||
|
if self.session.settings['sound']['indicate_audio'] and utils.is_audio_or_video(post):
|
||||||
|
self.session.sound.play("audio.ogg")
|
||||||
|
if self.session.settings['sound']['indicate_img'] and utils.is_image(post):
|
||||||
|
self.session.sound.play("image.ogg")
|
||||||
|
can_share = self.can_share()
|
||||||
|
pub.sendMessage("toggleShare", shareable=can_share)
|
||||||
|
self.buffer.boost.Enable(can_share)
|
||||||
|
|
||||||
|
def audio(self, url='', *args, **kwargs):
|
||||||
|
if sound.URLPlayer.player.is_playing():
|
||||||
|
return sound.URLPlayer.stop_audio()
|
||||||
|
item = self.get_item()
|
||||||
|
if item == None:
|
||||||
|
return
|
||||||
|
urls = utils.get_media_urls(item)
|
||||||
|
if len(urls) == 1:
|
||||||
|
url=urls[0]
|
||||||
|
elif len(urls) > 1:
|
||||||
|
urls_list = dialogs.urlList.urlList()
|
||||||
|
urls_list.populate_list(urls)
|
||||||
|
if urls_list.get_response() == widgetUtils.OK:
|
||||||
|
url=urls_list.get_string()
|
||||||
|
if hasattr(urls_list, "destroy"): urls_list.destroy()
|
||||||
|
if url != '':
|
||||||
|
# try:
|
||||||
|
sound.URLPlayer.play(url, self.session.settings["sound"]["volume"])
|
||||||
|
# except:
|
||||||
|
# log.error("Exception while executing audio method.")
|
||||||
|
|
||||||
|
def url(self, url='', announce=True, *args, **kwargs):
|
||||||
|
if url == '':
|
||||||
|
post = self.get_item()
|
||||||
|
if post.reblog != None:
|
||||||
|
urls = utils.find_urls(post.reblog)
|
||||||
|
else:
|
||||||
|
urls = utils.find_urls(post)
|
||||||
|
if len(urls) == 1:
|
||||||
|
url=urls[0]
|
||||||
|
elif len(urls) > 1:
|
||||||
|
urls_list = dialogs.urlList.urlList()
|
||||||
|
urls_list.populate_list(urls)
|
||||||
|
if urls_list.get_response() == widgetUtils.OK:
|
||||||
|
url=urls_list.get_string()
|
||||||
|
if hasattr(urls_list, "destroy"): urls_list.destroy()
|
||||||
|
if url != '':
|
||||||
|
if announce:
|
||||||
|
output.speak(_(u"Opening URL..."), True)
|
||||||
|
webbrowser.open_new_tab(url)
|
||||||
|
|
||||||
|
def clear_list(self):
|
||||||
|
dlg = commonMessageDialogs.clear_list()
|
||||||
|
if dlg == widgetUtils.YES:
|
||||||
|
self.session.db[self.name] = []
|
||||||
|
self.buffer.list.clear()
|
||||||
|
|
||||||
|
def destroy_status(self, *args, **kwargs):
|
||||||
|
index = self.buffer.list.get_selected()
|
||||||
|
item = self.session.db[self.name][index]
|
||||||
|
if item.account.id != self.session.db["user_id"] or item.reblog != None:
|
||||||
|
output.speak(_("You can delete only your own posts."))
|
||||||
|
return
|
||||||
|
answer = mastodon_dialogs.delete_post_dialog()
|
||||||
|
if answer == True:
|
||||||
|
items = self.session.db[self.name]
|
||||||
|
try:
|
||||||
|
self.session.api.status_delete(id=item.id)
|
||||||
|
items.pop(index)
|
||||||
|
self.buffer.list.remove_item(index)
|
||||||
|
except Exception as e:
|
||||||
|
self.session.sound.play("error.ogg")
|
||||||
|
self.session.db[self.name] = items
|
||||||
|
|
||||||
|
def user_details(self):
|
||||||
|
item = self.get_item()
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_item_url(self):
|
||||||
|
post = self.get_item()
|
||||||
|
if post.reblog != None:
|
||||||
|
return post.reblog.url
|
||||||
|
return post.url
|
||||||
|
|
||||||
|
def open_in_browser(self, *args, **kwargs):
|
||||||
|
url = self.get_item_url()
|
||||||
|
output.speak(_("Opening item in web browser..."))
|
||||||
|
webbrowser.open(url)
|
||||||
|
|
||||||
|
def add_to_favorites(self):
|
||||||
|
item = self.get_item()
|
||||||
|
if item.reblog != None:
|
||||||
|
item = item.reblog
|
||||||
|
call_threaded(self.session.api_call, call_name="status_favourite", preexec_message=_("Adding to favorites..."), _sound="favourite.ogg", id=item.id)
|
||||||
|
|
||||||
|
def remove_from_favorites(self):
|
||||||
|
item = self.get_item()
|
||||||
|
if item.reblog != None:
|
||||||
|
item = item.reblog
|
||||||
|
call_threaded(self.session.api_call, call_name="status_unfavourite", preexec_message=_("Removing from favorites..."), _sound="favourite.ogg", id=item.id)
|
||||||
|
|
||||||
|
def toggle_favorite(self, *args, **kwargs):
|
||||||
|
item = self.get_item()
|
||||||
|
if item.reblog != None:
|
||||||
|
item = item.reblog
|
||||||
|
item = self.session.api.status(item.id)
|
||||||
|
if item.favourited == False:
|
||||||
|
call_threaded(self.session.api_call, call_name="status_favourite", preexec_message=_("Adding to favorites..."), _sound="favourite.ogg", id=item.id)
|
||||||
|
else:
|
||||||
|
call_threaded(self.session.api_call, call_name="status_unfavourite", preexec_message=_("Removing from favorites..."), _sound="favourite.ogg", id=item.id)
|
||||||
|
|
||||||
|
def toggle_bookmark(self, *args, **kwargs):
|
||||||
|
item = self.get_item()
|
||||||
|
if item.reblog != None:
|
||||||
|
item = item.reblog
|
||||||
|
item = self.session.api.status(item.id)
|
||||||
|
if item.bookmarked == False:
|
||||||
|
call_threaded(self.session.api_call, call_name="status_bookmark", preexec_message=_("Adding to bookmarks..."), _sound="favourite.ogg", id=item.id)
|
||||||
|
else:
|
||||||
|
call_threaded(self.session.api_call, call_name="status_unbookmark", preexec_message=_("Removing from bookmarks..."), _sound="favourite.ogg", id=item.id)
|
||||||
|
|
||||||
|
def view_item(self):
|
||||||
|
post = self.get_item()
|
||||||
|
# Update object so we can retrieve newer stats
|
||||||
|
post = self.session.api.status(id=post.id)
|
||||||
|
print(post)
|
||||||
|
msg = messages.viewPost(post, offset_hours=self.session.db["utc_offset"], item_url=self.get_item_url())
|
||||||
|
|
||||||
|
def ocr_image(self):
|
||||||
|
post = self.get_item()
|
||||||
|
media_list = []
|
||||||
|
pass
|
241
src/controller/buffers/mastodon/conversations.py
Normal file
241
src/controller/buffers/mastodon/conversations.py
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import wx
|
||||||
|
import widgetUtils
|
||||||
|
import output
|
||||||
|
from controller.mastodon import messages
|
||||||
|
from controller.buffers.mastodon.base import BaseBuffer
|
||||||
|
from mysc.thread_utils import call_threaded
|
||||||
|
from sessions.mastodon import utils, templates
|
||||||
|
from wxUI import buffers, commonMessageDialogs
|
||||||
|
log = logging.getLogger("controller.buffers.mastodon.conversations")
|
||||||
|
|
||||||
|
class ConversationListBuffer(BaseBuffer):
|
||||||
|
|
||||||
|
def create_buffer(self, parent, name):
|
||||||
|
self.buffer = buffers.mastodon.conversationListPanel(parent, name)
|
||||||
|
|
||||||
|
def get_item(self):
|
||||||
|
index = self.buffer.list.get_selected()
|
||||||
|
if index > -1 and self.session.db.get(self.name) != None and len(self.session.db[self.name]) > index:
|
||||||
|
return self.session.db[self.name][index]["last_status"]
|
||||||
|
|
||||||
|
def get_conversation(self):
|
||||||
|
index = self.buffer.list.get_selected()
|
||||||
|
if index > -1 and self.session.db.get(self.name) != None:
|
||||||
|
return self.session.db[self.name][index]
|
||||||
|
|
||||||
|
def get_formatted_message(self):
|
||||||
|
return self.compose_function(self.get_conversation(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])[1]
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
conversation = self.get_conversation()
|
||||||
|
if conversation == None:
|
||||||
|
return
|
||||||
|
template = self.session.settings["templates"]["conversation"]
|
||||||
|
post_template = self.session.settings["templates"]["post"]
|
||||||
|
t = templates.render_conversation(conversation=conversation, template=template, post_template=post_template, relative_times=self.session.settings["general"]["relative_times"], offset_hours=self.session.db["utc_offset"])
|
||||||
|
return t
|
||||||
|
|
||||||
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
|
current_time = time.time()
|
||||||
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
|
self.execution_time = current_time
|
||||||
|
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||||
|
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||||
|
count = self.session.settings["general"]["max_posts_per_call"]
|
||||||
|
min_id = None
|
||||||
|
# toDo: Implement reverse timelines properly here.
|
||||||
|
# if (self.name != "favorites" and self.name != "bookmarks") and self.name in self.session.db and len(self.session.db[self.name]) > 0:
|
||||||
|
# min_id = self.session.db[self.name][-1].id
|
||||||
|
try:
|
||||||
|
results = getattr(self.session.api, self.function)(min_id=min_id, limit=count, *self.args, **self.kwargs)
|
||||||
|
results.reverse()
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
new_position, number_of_items = self.order_buffer(results)
|
||||||
|
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||||
|
self.put_items_on_list(number_of_items)
|
||||||
|
if new_position > -1:
|
||||||
|
self.buffer.list.select_item(new_position)
|
||||||
|
if number_of_items > 0 and self.name != "sent_posts" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(number_of_items)
|
||||||
|
return number_of_items
|
||||||
|
|
||||||
|
def get_more_items(self):
|
||||||
|
elements = []
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
max_id = self.session.db[self.name][0].last_status.id
|
||||||
|
else:
|
||||||
|
max_id = self.session.db[self.name][-1].last_status.id
|
||||||
|
try:
|
||||||
|
items = getattr(self.session.api, self.function)(max_id=max_id, limit=self.session.settings["general"]["max_posts_per_call"], *self.args, **self.kwargs)
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
items_db = self.session.db[self.name]
|
||||||
|
for i in items:
|
||||||
|
if utils.find_item(i, self.session.db[self.name]) == None:
|
||||||
|
elements.append(i)
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
items_db.insert(0, i)
|
||||||
|
else:
|
||||||
|
items_db.append(i)
|
||||||
|
self.session.db[self.name] = items_db
|
||||||
|
selection = self.buffer.list.get_selected()
|
||||||
|
log.debug("Retrieved %d items from cursored search in function %s." % (len(elements), self.function))
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
for i in elements:
|
||||||
|
conversation = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(True, *conversation)
|
||||||
|
else:
|
||||||
|
for i in items:
|
||||||
|
conversation = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(False, *conversation)
|
||||||
|
self.buffer.list.select_item(selection)
|
||||||
|
output.speak(_(u"%s items retrieved") % (str(len(elements))), True)
|
||||||
|
|
||||||
|
def get_item_position(self, conversation):
|
||||||
|
for i in range(len(self.session.db[self.name])):
|
||||||
|
if self.session.db[self.name][i].id == conversation.id:
|
||||||
|
return i
|
||||||
|
|
||||||
|
def order_buffer(self, data):
|
||||||
|
num = 0
|
||||||
|
focus_object = None
|
||||||
|
if self.session.db.get(self.name) == None:
|
||||||
|
self.session.db[self.name] = []
|
||||||
|
objects = self.session.db[self.name]
|
||||||
|
for i in data:
|
||||||
|
position = self.get_item_position(i)
|
||||||
|
if position != None:
|
||||||
|
conversation = self.session.db[self.name][position]
|
||||||
|
if conversation.last_status.id != i.last_status.id:
|
||||||
|
focus_object = i
|
||||||
|
objects.pop(position)
|
||||||
|
self.buffer.list.remove_item(position)
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
objects.append(i)
|
||||||
|
else:
|
||||||
|
objects.insert(0, i)
|
||||||
|
num = num+1
|
||||||
|
else:
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
objects.append(i)
|
||||||
|
else:
|
||||||
|
objects.insert(0, i)
|
||||||
|
num = num+1
|
||||||
|
self.session.db[self.name] = objects
|
||||||
|
if focus_object == None:
|
||||||
|
return (-1, num)
|
||||||
|
new_position = self.get_item_position(focus_object)
|
||||||
|
if new_position != None:
|
||||||
|
return (new_position, num)
|
||||||
|
return (-1, num)
|
||||||
|
|
||||||
|
def bind_events(self):
|
||||||
|
log.debug("Binding events...")
|
||||||
|
self.buffer.set_focus_function(self.onFocus)
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, widgetUtils.KEYPRESS, self.get_event)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_status, self.buffer.post)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
||||||
|
|
||||||
|
def fav(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def unfav(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def can_share(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def send_message(self):
|
||||||
|
return self.reply()
|
||||||
|
|
||||||
|
def onFocus(self, *args, **kwargs):
|
||||||
|
post = self.get_item()
|
||||||
|
if self.session.settings['sound']['indicate_audio'] and utils.is_audio_or_video(post):
|
||||||
|
self.session.sound.play("audio.ogg")
|
||||||
|
if self.session.settings['sound']['indicate_img'] and utils.is_image(post):
|
||||||
|
self.session.sound.play("image.ogg")
|
||||||
|
|
||||||
|
def destroy_status(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def reply(self, *args):
|
||||||
|
item = self.get_item()
|
||||||
|
conversation = self.get_conversation()
|
||||||
|
visibility = item.visibility
|
||||||
|
title = _("Reply to conversation with {}").format(conversation.accounts[0].username)
|
||||||
|
caption = _("Write your message here")
|
||||||
|
users = ["@{} ".format(user.acct) for user in conversation.accounts]
|
||||||
|
users_str = "".join(users)
|
||||||
|
post = messages.post(session=self.session, title=title, caption=caption, text=users_str)
|
||||||
|
visibility_settings = dict(public=0, unlisted=1, private=2, direct=3)
|
||||||
|
post.message.visibility.SetSelection(visibility_settings.get(visibility))
|
||||||
|
if item.sensitive:
|
||||||
|
post.message.sensitive.SetValue(item.sensitive)
|
||||||
|
post.message.spoiler.ChangeValue(item.spoiler_text)
|
||||||
|
post.message.on_sensitivity_changed()
|
||||||
|
response = post.message.ShowModal()
|
||||||
|
if response == wx.ID_OK:
|
||||||
|
post_data = post.get_data()
|
||||||
|
call_threaded(self.session.send_post, reply_to=item.id, posts=post_data, visibility=visibility)
|
||||||
|
if hasattr(post.message, "destroy"):
|
||||||
|
post.message.destroy()
|
||||||
|
|
||||||
|
class ConversationBuffer(BaseBuffer):
|
||||||
|
|
||||||
|
def __init__(self, post, *args, **kwargs):
|
||||||
|
self.post = post
|
||||||
|
super(ConversationBuffer, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
|
current_time = time.time()
|
||||||
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
|
self.execution_time = current_time
|
||||||
|
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||||
|
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||||
|
self.post = self.session.api.status(id=self.post.id)
|
||||||
|
# toDo: Implement reverse timelines properly here.
|
||||||
|
try:
|
||||||
|
results = []
|
||||||
|
items = getattr(self.session.api, self.function)(*self.args, **self.kwargs)
|
||||||
|
[results.append(item) for item in items.ancestors]
|
||||||
|
results.append(self.post)
|
||||||
|
[results.append(item) for item in items.descendants]
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
number_of_items = self.session.order_buffer(self.name, results)
|
||||||
|
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||||
|
self.put_items_on_list(number_of_items)
|
||||||
|
if number_of_items > 0 and self.name != "sent_posts" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(number_of_items)
|
||||||
|
return number_of_items
|
||||||
|
|
||||||
|
|
||||||
|
def get_more_items(self):
|
||||||
|
output.speak(_(u"This action is not supported for this buffer"), True)
|
||||||
|
|
||||||
|
def remove_buffer(self, force=False):
|
||||||
|
if force == False:
|
||||||
|
dlg = commonMessageDialogs.remove_buffer()
|
||||||
|
else:
|
||||||
|
dlg = widgetUtils.YES
|
||||||
|
if dlg == widgetUtils.YES:
|
||||||
|
if self.name in self.session.db:
|
||||||
|
self.session.db.pop(self.name)
|
||||||
|
return True
|
||||||
|
elif dlg == widgetUtils.NO:
|
||||||
|
return False
|
71
src/controller/buffers/mastodon/mentions.py
Normal file
71
src/controller/buffers/mastodon/mentions.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
from controller.buffers.mastodon.base import BaseBuffer
|
||||||
|
from sessions.mastodon import utils
|
||||||
|
|
||||||
|
log = logging.getLogger("controller.buffers.mastodon.mentions")
|
||||||
|
|
||||||
|
class MentionsBuffer(BaseBuffer):
|
||||||
|
|
||||||
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
|
current_time = time.time()
|
||||||
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
|
self.execution_time = current_time
|
||||||
|
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||||
|
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||||
|
count = self.session.settings["general"]["max_posts_per_call"]
|
||||||
|
min_id = None
|
||||||
|
# toDo: Implement reverse timelines properly here.
|
||||||
|
# if self.name != "favorites" and self.name in self.session.db and len(self.session.db[self.name]) > 0:
|
||||||
|
# min_id = self.session.db[self.name][-1].id
|
||||||
|
try:
|
||||||
|
items = getattr(self.session.api, self.function)(min_id=min_id, limit=count, exclude_types=["follow", "favourite", "reblog", "poll", "follow_request"], *self.args, **self.kwargs)
|
||||||
|
items.reverse()
|
||||||
|
results = [item.status for item in items if item.get("status") and item.type == "mention"]
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
number_of_items = self.session.order_buffer(self.name, results)
|
||||||
|
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||||
|
self.put_items_on_list(number_of_items)
|
||||||
|
if number_of_items > 0 and self.name != "sent_posts" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(number_of_items)
|
||||||
|
return number_of_items
|
||||||
|
|
||||||
|
def get_more_items(self):
|
||||||
|
elements = []
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
max_id = self.session.db[self.name][0].id
|
||||||
|
else:
|
||||||
|
max_id = self.session.db[self.name][-1].id
|
||||||
|
try:
|
||||||
|
items = getattr(self.session.api, self.function)(max_id=max_id, limit=self.session.settings["general"]["max_posts_per_call"], exclude_types=["follow", "favourite", "reblog", "poll", "follow_request"], *self.args, **self.kwargs)
|
||||||
|
items = [item.status for item in items if item.get("status") and item.type == "mention"]
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
items_db = self.session.db[self.name]
|
||||||
|
for i in items:
|
||||||
|
if utils.find_item(i, self.session.db[self.name]) == None:
|
||||||
|
elements.append(i)
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
items_db.insert(0, i)
|
||||||
|
else:
|
||||||
|
items_db.append(i)
|
||||||
|
self.session.db[self.name] = items_db
|
||||||
|
selection = self.buffer.list.get_selected()
|
||||||
|
log.debug("Retrieved %d items from cursored search in function %s." % (len(elements), self.function))
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
for i in elements:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(True, *post)
|
||||||
|
else:
|
||||||
|
for i in items:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(False, *post)
|
||||||
|
self.buffer.list.select_item(selection)
|
||||||
|
output.speak(_(u"%s items retrieved") % (str(len(elements))), True)
|
202
src/controller/buffers/mastodon/users.py
Normal file
202
src/controller/buffers/mastodon/users.py
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
import wx
|
||||||
|
import widgetUtils
|
||||||
|
import output
|
||||||
|
from mysc.thread_utils import call_threaded
|
||||||
|
from controller.buffers.mastodon.base import BaseBuffer
|
||||||
|
from controller.mastodon import messages
|
||||||
|
from sessions.mastodon import templates, utils
|
||||||
|
from wxUI import buffers, commonMessageDialogs
|
||||||
|
|
||||||
|
log = logging.getLogger("controller.buffers.mastodon.conversations")
|
||||||
|
|
||||||
|
class UserBuffer(BaseBuffer):
|
||||||
|
|
||||||
|
def create_buffer(self, parent, name):
|
||||||
|
self.buffer = buffers.mastodon.userPanel(parent, name)
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
user = self.get_item()
|
||||||
|
if user == None:
|
||||||
|
return
|
||||||
|
template = self.session.settings["templates"]["person"]
|
||||||
|
t = templates.render_user(user=user, template=template, relative_times=self.session.settings["general"]["relative_times"], offset_hours=self.session.db["utc_offset"])
|
||||||
|
return t
|
||||||
|
|
||||||
|
def bind_events(self):
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, widgetUtils.KEYPRESS, self.get_event)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_status, self.buffer.post)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.send_message, self.buffer.message)
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.user_actions, self.buffer.actions)
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
||||||
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
||||||
|
|
||||||
|
def fav(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def unfav(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def can_share(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def reply(self, *args, **kwargs):
|
||||||
|
return self.send_message()
|
||||||
|
|
||||||
|
def send_message(self, *args, **kwargs):
|
||||||
|
item = self.get_item()
|
||||||
|
title = _("New conversation with {}").format(item.username)
|
||||||
|
caption = _("Write your message here")
|
||||||
|
users_str = "@{} ".format(item.acct)
|
||||||
|
post = messages.post(session=self.session, title=title, caption=caption, text=users_str)
|
||||||
|
post.message.visibility.SetSelection(3)
|
||||||
|
response = post.message.ShowModal()
|
||||||
|
if response == wx.ID_OK:
|
||||||
|
post_data = post.get_data()
|
||||||
|
call_threaded(self.session.send_post, posts=post_data, visibility="direct")
|
||||||
|
if hasattr(post.message, "destroy"):
|
||||||
|
post.message.destroy()
|
||||||
|
|
||||||
|
def audio(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def url(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def destroy_status(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
|
current_time = time.time()
|
||||||
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
|
self.execution_time = current_time
|
||||||
|
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||||
|
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||||
|
count = self.session.settings["general"]["max_posts_per_call"]
|
||||||
|
# toDo: Implement reverse timelines properly here.
|
||||||
|
try:
|
||||||
|
results = getattr(self.session.api, self.function)(limit=count, *self.args, **self.kwargs)
|
||||||
|
if hasattr(results, "_pagination_next") and self.name not in self.session.db["pagination_info"]:
|
||||||
|
self.session.db["pagination_info"][self.name] = results._pagination_next
|
||||||
|
results.reverse()
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
number_of_items = self.session.order_buffer(self.name, results)
|
||||||
|
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||||
|
if hasattr(self, "finished_timeline") and self.finished_timeline == False:
|
||||||
|
if "-followers" in self.name or "-following" in self.name:
|
||||||
|
self.username = self.session.api.account(id=self.kwargs.get("id")).username
|
||||||
|
self.finished_timeline = True
|
||||||
|
self.put_items_on_list(number_of_items)
|
||||||
|
if number_of_items > 0 and self.name != "sent_posts" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(number_of_items)
|
||||||
|
return number_of_items
|
||||||
|
|
||||||
|
def get_more_items(self):
|
||||||
|
elements = []
|
||||||
|
pagination_info = self.session.db["pagination_info"].get(self.name)
|
||||||
|
if pagination_info == None:
|
||||||
|
output.speak(_("There are no more items in this buffer."))
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
items = self.session.api.fetch_next(pagination_info)
|
||||||
|
if hasattr(items, "_pagination_next"):
|
||||||
|
self.session.db["pagination_info"][self.name] = items._pagination_next
|
||||||
|
except Exception as e:
|
||||||
|
log.exception("Error %s" % (str(e)))
|
||||||
|
return
|
||||||
|
items_db = self.session.db[self.name]
|
||||||
|
for i in items:
|
||||||
|
if utils.find_item(i, self.session.db[self.name]) == None:
|
||||||
|
elements.append(i)
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
items_db.insert(0, i)
|
||||||
|
else:
|
||||||
|
items_db.append(i)
|
||||||
|
self.session.db[self.name] = items_db
|
||||||
|
selection = self.buffer.list.get_selected()
|
||||||
|
log.debug("Retrieved %d items from cursored search in function %s." % (len(elements), self.function))
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
for i in elements:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(True, *post)
|
||||||
|
else:
|
||||||
|
for i in items:
|
||||||
|
post = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
|
||||||
|
self.buffer.list.insert_item(False, *post)
|
||||||
|
self.buffer.list.select_item(selection)
|
||||||
|
output.speak(_(u"%s items retrieved") % (str(len(elements))), True)
|
||||||
|
|
||||||
|
def get_item_url(self):
|
||||||
|
item = self.get_item()
|
||||||
|
return item.url
|
||||||
|
|
||||||
|
def user_details(self):
|
||||||
|
item = self.get_item()
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add_to_favorites(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove_from_favorites(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def toggle_favorite(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def view_item(self):
|
||||||
|
item = self.get_item()
|
||||||
|
print(item)
|
||||||
|
|
||||||
|
def ocr_image(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove_buffer(self, force=False):
|
||||||
|
if "-followers" in self.name:
|
||||||
|
if force == False:
|
||||||
|
dlg = commonMessageDialogs.remove_buffer()
|
||||||
|
else:
|
||||||
|
dlg = widgetUtils.YES
|
||||||
|
if dlg == widgetUtils.YES:
|
||||||
|
if self.kwargs.get("id") in self.session.settings["other_buffers"]["followers_timelines"]:
|
||||||
|
self.session.settings["other_buffers"]["followers_timelines"].remove(self.kwargs.get("id"))
|
||||||
|
self.session.settings.write()
|
||||||
|
if self.name in self.session.db:
|
||||||
|
self.session.db.pop(self.name)
|
||||||
|
return True
|
||||||
|
elif dlg == widgetUtils.NO:
|
||||||
|
return False
|
||||||
|
elif "-following" in self.name:
|
||||||
|
if force == False:
|
||||||
|
dlg = commonMessageDialogs.remove_buffer()
|
||||||
|
else:
|
||||||
|
dlg = widgetUtils.YES
|
||||||
|
if dlg == widgetUtils.YES:
|
||||||
|
if self.kwargs.get("id") in self.session.settings["other_buffers"]["following_timelines"]:
|
||||||
|
self.session.settings["other_buffers"]["following_timelines"].remove(self.kwargs.get("id"))
|
||||||
|
self.session.settings.write()
|
||||||
|
if self.name in self.session.db:
|
||||||
|
self.session.db.pop(self.name)
|
||||||
|
return True
|
||||||
|
elif dlg == widgetUtils.NO:
|
||||||
|
return False
|
||||||
|
elif "-searchUser" in self.name:
|
||||||
|
if force == False:
|
||||||
|
dlg = commonMessageDialogs.remove_buffer()
|
||||||
|
else:
|
||||||
|
dlg = widgetUtils.YES
|
||||||
|
if dlg == widgetUtils.YES:
|
||||||
|
if self.name in self.session.db:
|
||||||
|
self.session.db.pop(self.name)
|
||||||
|
return True
|
||||||
|
elif dlg == widgetUtils.NO:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True)
|
||||||
|
return False
|
@@ -1,14 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import time
|
import time
|
||||||
import platform
|
import wx
|
||||||
if platform.system() == "Windows":
|
|
||||||
import wx
|
|
||||||
from wxUI import buffers, dialogs, commonMessageDialogs, menus
|
|
||||||
from controller import user
|
|
||||||
elif platform.system() == "Linux":
|
|
||||||
from gi.repository import Gtk
|
|
||||||
from gtkUI import buffers, dialogs, commonMessageDialogs
|
|
||||||
from controller import messages
|
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import arrow
|
import arrow
|
||||||
import webbrowser
|
import webbrowser
|
||||||
@@ -19,12 +11,15 @@ import languageHandler
|
|||||||
import logging
|
import logging
|
||||||
from audio_services import youtube_utils
|
from audio_services import youtube_utils
|
||||||
from controller.buffers.base import base
|
from controller.buffers.base import base
|
||||||
from sessions.twitter import compose, utils, reduce
|
from sessions.twitter import compose, utils, reduce, templates
|
||||||
from mysc.thread_utils import call_threaded
|
from mysc.thread_utils import call_threaded
|
||||||
from tweepy.error import TweepError
|
from tweepy.errors import TweepyException
|
||||||
from tweepy.cursor import Cursor
|
from tweepy.cursor import Cursor
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
|
from extra import ocr
|
||||||
from sessions.twitter.long_tweets import twishort, tweets
|
from sessions.twitter.long_tweets import twishort, tweets
|
||||||
|
from wxUI import buffers, dialogs, commonMessageDialogs, menus
|
||||||
|
from controller.twitter import user, messages
|
||||||
|
|
||||||
log = logging.getLogger("controller.buffers")
|
log = logging.getLogger("controller.buffers")
|
||||||
|
|
||||||
@@ -40,9 +35,9 @@ class BaseBuffer(base.Buffer):
|
|||||||
super(BaseBuffer, self).__init__(parent, function, *args, **kwargs)
|
super(BaseBuffer, self).__init__(parent, function, *args, **kwargs)
|
||||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||||
if bufferType != None:
|
if bufferType != None:
|
||||||
self.buffer = getattr(buffers, bufferType)(parent, name)
|
self.buffer = getattr(buffers.twitter, bufferType)(parent, name)
|
||||||
else:
|
else:
|
||||||
self.buffer = buffers.basePanel(parent, name)
|
self.buffer = buffers.twitter.basePanel(parent, name)
|
||||||
self.invisible = True
|
self.invisible = True
|
||||||
self.name = name
|
self.name = name
|
||||||
self.type = self.buffer.type
|
self.type = self.buffer.type
|
||||||
@@ -84,42 +79,15 @@ class BaseBuffer(base.Buffer):
|
|||||||
return _(u"Unknown buffer")
|
return _(u"Unknown buffer")
|
||||||
|
|
||||||
def post_status(self, *args, **kwargs):
|
def post_status(self, *args, **kwargs):
|
||||||
item = None
|
title = _("Tweet")
|
||||||
title = _(u"Tweet")
|
caption = _("Write the tweet here")
|
||||||
caption = _(u"Write the tweet here")
|
|
||||||
tweet = messages.tweet(self.session, title, caption, "")
|
tweet = messages.tweet(self.session, title, caption, "")
|
||||||
if tweet.message.get_response() == widgetUtils.OK:
|
response = tweet.message.ShowModal()
|
||||||
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
if response == wx.ID_OK:
|
||||||
config.app["app-settings"]["longtweet"] = tweet.message.long_tweet.GetValue()
|
tweet_data = tweet.get_tweet_data()
|
||||||
config.app.write()
|
call_threaded(self.session.send_tweet, *tweet_data)
|
||||||
text = tweet.message.get_text()
|
if hasattr(tweet.message, "destroy"):
|
||||||
if len(text) > 280 and tweet.message.get("long_tweet") == True:
|
tweet.message.destroy()
|
||||||
if not hasattr(tweet, "attachments"):
|
|
||||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text)
|
|
||||||
else:
|
|
||||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
|
|
||||||
if not hasattr(tweet, "attachments") or len(tweet.attachments) == 0:
|
|
||||||
item = self.session.api_call(call_name="update_status", status=text, _sound="tweet_send.ogg", tweet_mode="extended")
|
|
||||||
else:
|
|
||||||
call_threaded(self.post_with_media, text=text, attachments=tweet.attachments)
|
|
||||||
# We will no longer will reuse the sent item from here as Streaming API should give us the new and correct item.
|
|
||||||
# but in case we'd need it, just uncomment the following couple of lines and make sure we reduce the item correctly.
|
|
||||||
# if item != None:
|
|
||||||
# pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
|
||||||
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
|
|
||||||
self.session.settings.write()
|
|
||||||
|
|
||||||
def post_with_media(self, text, attachments):
|
|
||||||
media_ids = []
|
|
||||||
for i in attachments:
|
|
||||||
img = self.session.twitter.media_upload(i["file"])
|
|
||||||
self.session.twitter.create_media_metadata(media_id=img.media_id, alt_text=i["description"])
|
|
||||||
media_ids.append(img.media_id)
|
|
||||||
item = self.session.twitter.update_status(status=text, media_ids=media_ids)
|
|
||||||
# We will no longer will reuse the sent item from here as Streaming API should give us the new and correct item.
|
|
||||||
# but in case we'd need it, just uncomment the following couple of lines and make sure we reduce the item correctly.
|
|
||||||
# if item != None:
|
|
||||||
# pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
|
||||||
|
|
||||||
def get_formatted_message(self):
|
def get_formatted_message(self):
|
||||||
if self.type == "dm" or self.name == "direct_messages":
|
if self.type == "dm" or self.name == "direct_messages":
|
||||||
@@ -127,8 +95,10 @@ class BaseBuffer(base.Buffer):
|
|||||||
return self.get_message()
|
return self.get_message()
|
||||||
|
|
||||||
def get_message(self):
|
def get_message(self):
|
||||||
|
template = self.session.settings["templates"]["tweet"]
|
||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
return " ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session))
|
t = templates.render_tweet(tweet, template, self.session, relative_times=self.session.settings["general"]["relative_times"], offset_seconds=self.session.db["utc_offset"])
|
||||||
|
return t
|
||||||
|
|
||||||
def get_full_tweet(self):
|
def get_full_tweet(self):
|
||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
@@ -140,7 +110,7 @@ class BaseBuffer(base.Buffer):
|
|||||||
try:
|
try:
|
||||||
tweet = self.session.twitter.get_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended")
|
tweet = self.session.twitter.get_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended")
|
||||||
tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities)
|
tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities)
|
||||||
except TweepError as e:
|
except TweepyException as e:
|
||||||
utils.twitter_error(e)
|
utils.twitter_error(e)
|
||||||
return
|
return
|
||||||
if message != None:
|
if message != None:
|
||||||
@@ -151,7 +121,7 @@ class BaseBuffer(base.Buffer):
|
|||||||
try:
|
try:
|
||||||
tweet = self.session.twitter.get_status(id=l, include_ext_alt_text=True, tweet_mode="extended")
|
tweet = self.session.twitter.get_status(id=l, include_ext_alt_text=True, tweet_mode="extended")
|
||||||
tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities)
|
tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities)
|
||||||
except TweepError as e:
|
except TweepyException as e:
|
||||||
utils.twitter_error(e)
|
utils.twitter_error(e)
|
||||||
return
|
return
|
||||||
l = tweets.is_long(tweet)
|
l = tweets.is_long(tweet)
|
||||||
@@ -167,7 +137,7 @@ class BaseBuffer(base.Buffer):
|
|||||||
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
|
||||||
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
|
||||||
if self.name != "direct_messages":
|
if self.name != "direct_messages":
|
||||||
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
|
val = self.session.call_paged(self.function, self.name, *self.args, **self.kwargs)
|
||||||
else:
|
else:
|
||||||
# 50 results are allowed per API call, so let's assume max value can be 50.
|
# 50 results are allowed per API call, so let's assume max value can be 50.
|
||||||
# reference: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/list-events
|
# reference: https://developer.twitter.com/en/docs/twitter-api/v1/direct-messages/sending-and-receiving/api-reference/list-events
|
||||||
@@ -191,17 +161,17 @@ class BaseBuffer(base.Buffer):
|
|||||||
log.debug("Retrieved %d items from the cursored search on function %s." %(len(val), self.function))
|
log.debug("Retrieved %d items from the cursored search on function %s." %(len(val), self.function))
|
||||||
user_ids = [item.message_create["sender_id"] for item in val]
|
user_ids = [item.message_create["sender_id"] for item in val]
|
||||||
self.session.save_users(user_ids)
|
self.session.save_users(user_ids)
|
||||||
except TweepError as e:
|
except TweepyException as e:
|
||||||
log.error("Error %s: %s" % (e.api_code, e.reason))
|
log.exception("Error %s" % (str(e)))
|
||||||
return
|
return
|
||||||
number_of_items = self.session.order_buffer(self.name, val)
|
number_of_items = self.session.order_buffer(self.name, val)
|
||||||
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
log.debug("Number of items retrieved: %d" % (number_of_items,))
|
||||||
self.put_items_on_list(number_of_items)
|
self.put_items_on_list(number_of_items)
|
||||||
if hasattr(self, "finished_timeline") and self.finished_timeline == False:
|
if hasattr(self, "finished_timeline") and self.finished_timeline == False:
|
||||||
if "-timeline" in self.name:
|
if "-timeline" in self.name:
|
||||||
self.username = val[0].user.screen_name
|
self.username = self.session.get_user(self.kwargs.get("user_id")).screen_name
|
||||||
elif "-favorite" in self.name:
|
elif "-favorite" in self.name:
|
||||||
self.username = self.session.api_call("get_user", **self.kwargs).screen_name
|
self.username = self.session.get_user(self.kwargs.get("user_id")).screen_name
|
||||||
self.finished_timeline = True
|
self.finished_timeline = True
|
||||||
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
self.session.sound.play(self.sound)
|
self.session.sound.play(self.sound)
|
||||||
@@ -229,15 +199,15 @@ class BaseBuffer(base.Buffer):
|
|||||||
last_id = self.session.db[self.name][-1].id
|
last_id = self.session.db[self.name][-1].id
|
||||||
try:
|
try:
|
||||||
items = getattr(self.session.twitter, self.function)(max_id=last_id, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs)
|
items = getattr(self.session.twitter, self.function)(max_id=last_id, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs)
|
||||||
except TweepError as e:
|
except TweepyException as e:
|
||||||
log.error("Error %s: %s" % (e.api_code, e.reason))
|
log.exception("Error %s" % (str(e)))
|
||||||
return
|
return
|
||||||
if items == None:
|
if items == None:
|
||||||
return
|
return
|
||||||
items_db = self.session.db[self.name]
|
items_db = self.session.db[self.name]
|
||||||
self.session.add_users_from_results(items)
|
self.session.add_users_from_results(items)
|
||||||
for i in items:
|
for i in items:
|
||||||
if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i.id, self.session.db[self.name]) == None:
|
if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i, self.session.db[self.name]) == None:
|
||||||
i = reduce.reduce_tweet(i)
|
i = reduce.reduce_tweet(i)
|
||||||
i = self.session.check_quoted_status(i)
|
i = self.session.check_quoted_status(i)
|
||||||
i = self.session.check_long_tweet(i)
|
i = self.session.check_long_tweet(i)
|
||||||
@@ -334,9 +304,6 @@ class BaseBuffer(base.Buffer):
|
|||||||
self.buffer.list.insert_item(True, *tweet)
|
self.buffer.list.insert_item(True, *tweet)
|
||||||
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
output.speak(" ".join(tweet[:2]), speech=self.session.settings["reporting"]["speech_reporting"], braille=self.session.settings["reporting"]["braille_reporting"])
|
output.speak(" ".join(tweet[:2]), speech=self.session.settings["reporting"]["speech_reporting"], braille=self.session.settings["reporting"]["braille_reporting"])
|
||||||
#Improve performance on Windows
|
|
||||||
# if platform.system() == "Windows":
|
|
||||||
# call_threaded(utils.is_audio,item)
|
|
||||||
|
|
||||||
def bind_events(self):
|
def bind_events(self):
|
||||||
log.debug("Binding events...")
|
log.debug("Binding events...")
|
||||||
@@ -347,7 +314,6 @@ class BaseBuffer(base.Buffer):
|
|||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.share_item, self.buffer.retweet)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.share_item, self.buffer.retweet)
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.send_message, self.buffer.dm)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.send_message, self.buffer.dm)
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
||||||
# Replace for the correct way in other platforms.
|
|
||||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
||||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
||||||
|
|
||||||
@@ -416,13 +382,18 @@ class BaseBuffer(base.Buffer):
|
|||||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
|
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
|
||||||
return tweet
|
return tweet
|
||||||
|
|
||||||
|
def can_share(self):
|
||||||
|
tweet = self.get_right_tweet()
|
||||||
|
user = self.session.get_user(tweet.user)
|
||||||
|
is_protected = user.protected
|
||||||
|
return is_protected==False
|
||||||
|
|
||||||
@_tweets_exist
|
@_tweets_exist
|
||||||
def reply(self, *args, **kwargs):
|
def reply(self, *args, **kwargs):
|
||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
user = self.session.get_user(tweet.user)
|
user = self.session.get_user(tweet.user)
|
||||||
screen_name = user.screen_name
|
screen_name = user.screen_name
|
||||||
id = tweet.id
|
id = tweet.id
|
||||||
twishort_enabled = hasattr(tweet, "twishort")
|
|
||||||
users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name")
|
users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name")
|
||||||
ids = utils.get_all_mentioned(tweet, self.session.db, field="id")
|
ids = utils.get_all_mentioned(tweet, self.session.db, field="id")
|
||||||
# Build the window title
|
# Build the window title
|
||||||
@@ -430,38 +401,14 @@ class BaseBuffer(base.Buffer):
|
|||||||
title=_("Reply to {arg0}").format(arg0=screen_name)
|
title=_("Reply to {arg0}").format(arg0=screen_name)
|
||||||
else:
|
else:
|
||||||
title=_("Reply")
|
title=_("Reply")
|
||||||
message = messages.reply(self.session, title, _(u"Reply to %s") % (screen_name,), "", users=users, ids=ids)
|
message = messages.reply(self.session, title, _("Reply to %s") % (screen_name,), "", users=users, ids=ids)
|
||||||
if message.message.get_response() == widgetUtils.OK:
|
if message.message.ShowModal() == widgetUtils.OK:
|
||||||
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
||||||
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
|
|
||||||
if len(users) > 0:
|
if len(users) > 0:
|
||||||
config.app["app-settings"]["mention_all"] = message.message.mentionAll.GetValue()
|
config.app["app-settings"]["mention_all"] = message.message.mention_all.GetValue()
|
||||||
config.app.write()
|
config.app.write()
|
||||||
params = {"_sound": "reply_send.ogg", "in_reply_to_status_id": id, "tweet_mode": "extended"}
|
tweet_data = dict(text=message.message.text.GetValue(), attachments=message.attachments, poll_options=message.poll_options, poll_period=message.poll_period)
|
||||||
text = message.message.get_text()
|
call_threaded(self.session.reply, in_reply_to_status_id=id, text=message.message.text.GetValue(), attachments=message.attachments, exclude_reply_user_ids=message.get_ids())
|
||||||
if twishort_enabled == False:
|
|
||||||
excluded_ids = message.get_ids()
|
|
||||||
params["exclude_reply_user_ids"] =excluded_ids
|
|
||||||
params["auto_populate_reply_metadata"] =True
|
|
||||||
else:
|
|
||||||
mentioned_people = message.get_people()
|
|
||||||
text = "@"+screen_name+" "+mentioned_people+u" "+text
|
|
||||||
if len(text) > 280 and message.message.get("long_tweet") == True:
|
|
||||||
if message.image == None:
|
|
||||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text)
|
|
||||||
else:
|
|
||||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
|
|
||||||
params["status"] = text
|
|
||||||
if message.image == None:
|
|
||||||
params["call_name"] = "update_status"
|
|
||||||
else:
|
|
||||||
params["call_name"] = "update_status_with_media"
|
|
||||||
params["media"] = message.file
|
|
||||||
item = self.session.api_call(**params)
|
|
||||||
# We will no longer will reuse the sent item from here as Streaming API should give us the new and correct item.
|
|
||||||
# but in case we'd need it, just uncomment the following couple of lines and make sure we reduce the item correctly.
|
|
||||||
# if item != None:
|
|
||||||
# pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
|
||||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
if hasattr(message.message, "destroy"): message.message.destroy()
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
|
|
||||||
@@ -477,25 +424,23 @@ class BaseBuffer(base.Buffer):
|
|||||||
else:
|
else:
|
||||||
screen_name = self.session.get_user(tweet.user).screen_name
|
screen_name = self.session.get_user(tweet.user).screen_name
|
||||||
users = utils.get_all_users(tweet, self.session)
|
users = utils.get_all_users(tweet, self.session)
|
||||||
dm = messages.dm(self.session, _(u"Direct message to %s") % (screen_name,), _(u"New direct message"), users)
|
dm = messages.dm(self.session, _("Direct message to %s") % (screen_name,), _("New direct message"), users)
|
||||||
if dm.message.get_response() == widgetUtils.OK:
|
if dm.message.ShowModal() == widgetUtils.OK:
|
||||||
screen_name = dm.message.get("cb")
|
screen_name = dm.message.cb.GetValue()
|
||||||
user = self.session.get_user_by_screen_name(screen_name)
|
user = self.session.get_user_by_screen_name(screen_name)
|
||||||
recipient_id = user
|
recipient_id = user
|
||||||
text = dm.message.get_text()
|
text = dm.message.text.GetValue()
|
||||||
val = self.session.api_call(call_name="send_direct_message", recipient_id=recipient_id, text=text)
|
if len(dm.attachments) > 0:
|
||||||
if val != None:
|
attachment = dm.attachments[0]
|
||||||
sent_dms = self.session.db["sent_direct_messages"]
|
else:
|
||||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
attachment = None
|
||||||
sent_dms.append(val)
|
call_threaded(self.session.direct_message, text=text, recipient=recipient_id, attachment=attachment)
|
||||||
else:
|
|
||||||
sent_dms.insert(0, val)
|
|
||||||
self.session.db["sent_direct_messages"] = sent_dms
|
|
||||||
pub.sendMessage("sent-dm", data=val, user=self.session.db["user_name"])
|
|
||||||
if hasattr(dm.message, "destroy"): dm.message.destroy()
|
if hasattr(dm.message, "destroy"): dm.message.destroy()
|
||||||
|
|
||||||
@_tweets_exist
|
@_tweets_exist
|
||||||
def share_item(self, *args, **kwargs):
|
def share_item(self, *args, **kwargs):
|
||||||
|
if self.can_share() == False:
|
||||||
|
return output.speak(_("This action is not supported on protected accounts."))
|
||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
id = tweet.id
|
id = tweet.id
|
||||||
if self.session.settings["general"]["retweet_mode"] == "ask":
|
if self.session.settings["general"]["retweet_mode"] == "ask":
|
||||||
@@ -509,44 +454,24 @@ class BaseBuffer(base.Buffer):
|
|||||||
else:
|
else:
|
||||||
self._retweet_with_comment(tweet, id)
|
self._retweet_with_comment(tweet, id)
|
||||||
|
|
||||||
def _retweet_with_comment(self, tweet, id, comment=''):
|
def _retweet_with_comment(self, tweet, id):
|
||||||
# If quoting a retweet, let's quote the original tweet instead the retweet.
|
|
||||||
if hasattr(tweet, "retweeted_status"):
|
if hasattr(tweet, "retweeted_status"):
|
||||||
tweet = tweet.retweeted_status
|
tweet = tweet.retweeted_status
|
||||||
if hasattr(tweet, "full_text"):
|
retweet = messages.tweet(session=self.session, title=_("Quote"), caption=_("Add your comment to the tweet"), max=256, thread_mode=False)
|
||||||
comments = tweet.full_text
|
if retweet.message.ShowModal() == widgetUtils.OK:
|
||||||
else:
|
text = retweet.message.text.GetValue()
|
||||||
comments = tweet.text
|
tweet_data = dict(text=text, attachments=retweet.attachments, poll_period=retweet.poll_period, poll_options=retweet.poll_options)
|
||||||
retweet = messages.tweet(self.session, _(u"Quote"), _(u"Add your comment to the tweet"), u"“@%s: %s ”" % (self.session.get_user(tweet.user).screen_name, comments), max=256, messageType="retweet")
|
tweet_data.update(quote_tweet_id=id)
|
||||||
if comment != '':
|
call_threaded(self.session.send_tweet, *[tweet_data])
|
||||||
retweet.message.set_text(comment)
|
if hasattr(retweet.message, "destroy"):
|
||||||
if retweet.message.get_response() == widgetUtils.OK:
|
retweet.message.Destroy()
|
||||||
text = retweet.message.get_text()
|
|
||||||
text = text+" https://twitter.com/{0}/status/{1}".format(self.session.get_user(tweet.user).screen_name, id)
|
|
||||||
if retweet.image == None:
|
|
||||||
# We will no longer will reuse the sent item from here as Streaming API should give us the new and correct item.
|
|
||||||
# but in case we'd need it, just uncomment the following couple of lines and make sure we reduce the item correctly.
|
|
||||||
item = self.session.api_call(call_name="update_status", _sound="retweet_send.ogg", status=text, in_reply_to_status_id=id, tweet_mode="extended")
|
|
||||||
# if item != None:
|
|
||||||
# new_item = self.session.twitter.get_status(id=item.id, include_ext_alt_text=True, tweet_mode="extended")
|
|
||||||
# pub.sendMessage("sent-tweet", data=new_item, user=self.session.db["user_name"])
|
|
||||||
else:
|
|
||||||
call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, media=retweet.image)
|
|
||||||
if hasattr(retweet.message, "destroy"): retweet.message.destroy()
|
|
||||||
|
|
||||||
def _direct_retweet(self, id):
|
def _direct_retweet(self, id):
|
||||||
item = self.session.api_call(call_name="retweet", _sound="retweet_send.ogg", id=id)
|
item = self.session.api_call(call_name="retweet", _sound="retweet_send.ogg", id=id)
|
||||||
# We will no longer will reuse the sent item from here as Streaming API should give us the new and correct item.
|
|
||||||
# but in case we'd need it, just uncomment the following couple of lines and make sure we reduce the item correctly.
|
|
||||||
# if item != None:
|
|
||||||
# Retweets are returned as non-extended tweets, so let's get the object as extended
|
|
||||||
# just before sending the event message. See https://github.com/manuelcortez/TWBlue/issues/253
|
|
||||||
# item = self.session.twitter.get_status(id=item.id, include_ext_alt_text=True, tweet_mode="extended")
|
|
||||||
# pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
|
||||||
|
|
||||||
def onFocus(self, *args, **kwargs):
|
def onFocus(self, *args, **kwargs):
|
||||||
tweet = self.get_tweet()
|
tweet = self.get_tweet()
|
||||||
if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True:
|
if self.session.settings["general"]["relative_times"] == True:
|
||||||
# fix this:
|
# fix this:
|
||||||
original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()].created_at, locale="en")
|
original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()].created_at, locale="en")
|
||||||
ts = original_date.humanize(locale=languageHandler.getLanguage())
|
ts = original_date.humanize(locale=languageHandler.getLanguage())
|
||||||
@@ -557,6 +482,9 @@ class BaseBuffer(base.Buffer):
|
|||||||
self.session.sound.play("geo.ogg")
|
self.session.sound.play("geo.ogg")
|
||||||
if self.session.settings['sound']['indicate_img'] and utils.is_media(tweet):
|
if self.session.settings['sound']['indicate_img'] and utils.is_media(tweet):
|
||||||
self.session.sound.play("image.ogg")
|
self.session.sound.play("image.ogg")
|
||||||
|
can_share = self.can_share()
|
||||||
|
pub.sendMessage("toggleShare", shareable=can_share)
|
||||||
|
self.buffer.retweet.Enable(can_share)
|
||||||
|
|
||||||
def audio(self, url='', *args, **kwargs):
|
def audio(self, url='', *args, **kwargs):
|
||||||
if sound.URLPlayer.player.is_playing():
|
if sound.URLPlayer.player.is_playing():
|
||||||
@@ -611,13 +539,13 @@ class BaseBuffer(base.Buffer):
|
|||||||
items = self.session.db[self.name]
|
items = self.session.db[self.name]
|
||||||
try:
|
try:
|
||||||
if self.name == "direct_messages" or self.name == "sent_direct_messages":
|
if self.name == "direct_messages" or self.name == "sent_direct_messages":
|
||||||
self.session.twitter.destroy_direct_message(id=self.get_right_tweet().id)
|
self.session.twitter.delete_direct_message(id=self.get_right_tweet().id)
|
||||||
items.pop(index)
|
items.pop(index)
|
||||||
else:
|
else:
|
||||||
self.session.twitter.destroy_status(id=self.get_right_tweet().id)
|
self.session.twitter.destroy_status(id=self.get_right_tweet().id)
|
||||||
items.pop(index)
|
items.pop(index)
|
||||||
self.buffer.list.remove_item(index)
|
self.buffer.list.remove_item(index)
|
||||||
except TweepError:
|
except TweepyException:
|
||||||
self.session.sound.play("error.ogg")
|
self.session.sound.play("error.ogg")
|
||||||
self.session.db[self.name] = items
|
self.session.db[self.name] = items
|
||||||
|
|
||||||
@@ -644,8 +572,92 @@ class BaseBuffer(base.Buffer):
|
|||||||
original_tweet.text = utils.find_urls_in_text(original_tweet.text, original_tweet.entities)
|
original_tweet.text = utils.find_urls_in_text(original_tweet.text, original_tweet.entities)
|
||||||
return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"])
|
return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"])
|
||||||
|
|
||||||
def open_in_browser(self, *args, **kwargs):
|
def get_item_url(self):
|
||||||
tweet = self.get_tweet()
|
tweet = self.get_tweet()
|
||||||
output.speak(_(u"Opening item in web browser..."))
|
|
||||||
url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=self.session.get_user(tweet.user).screen_name, tweet_id=tweet.id)
|
url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=self.session.get_user(tweet.user).screen_name, tweet_id=tweet.id)
|
||||||
webbrowser.open(url)
|
return url
|
||||||
|
|
||||||
|
def open_in_browser(self, *args, **kwargs):
|
||||||
|
url = self.get_item_url()
|
||||||
|
output.speak(_(u"Opening item in web browser..."))
|
||||||
|
webbrowser.open(url)
|
||||||
|
|
||||||
|
def add_to_favorites(self):
|
||||||
|
id = self.get_tweet().id
|
||||||
|
call_threaded(self.session.api_call, call_name="create_favorite", _sound="favourite.ogg", id=id)
|
||||||
|
|
||||||
|
def remove_from_favorites(self):
|
||||||
|
id = self.get_tweet().id
|
||||||
|
call_threaded(self.session.api_call, call_name="destroy_favorite", id=id)
|
||||||
|
|
||||||
|
def toggle_favorite(self):
|
||||||
|
id = self.get_tweet().id
|
||||||
|
tweet = self.session.twitter.get_status(id=id, include_ext_alt_text=True, tweet_mode="extended")
|
||||||
|
if tweet.favorited == False:
|
||||||
|
call_threaded(self.session.api_call, call_name="create_favorite", _sound="favourite.ogg", id=id)
|
||||||
|
else:
|
||||||
|
call_threaded(self.session.api_call, call_name="destroy_favorite", id=id)
|
||||||
|
|
||||||
|
def view_item(self):
|
||||||
|
if self.type == "dm" or self.name == "direct_messages":
|
||||||
|
non_tweet = self.get_formatted_message()
|
||||||
|
item = self.get_right_tweet()
|
||||||
|
original_date = arrow.get(int(item.created_timestamp))
|
||||||
|
date = original_date.shift(seconds=self.session.db["utc_offset"]).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||||
|
msg = messages.viewTweet(non_tweet, [], False, date=date)
|
||||||
|
else:
|
||||||
|
tweet, tweetsList = self.get_full_tweet()
|
||||||
|
msg = messages.viewTweet(tweet, tweetsList, utc_offset=self.session.db["utc_offset"], item_url=self.get_item_url())
|
||||||
|
|
||||||
|
def reverse_geocode(self, geocoder):
|
||||||
|
try:
|
||||||
|
tweet = self.get_tweet()
|
||||||
|
if tweet.coordinates != None:
|
||||||
|
x = tweet.coordinates["coordinates"][0]
|
||||||
|
y = tweet.coordinates["coordinates"][1]
|
||||||
|
address = geocoder.reverse_geocode(y, x, language = languageHandler.curLang)
|
||||||
|
return address
|
||||||
|
else:
|
||||||
|
output.speak(_("There are no coordinates in this tweet"))
|
||||||
|
# except GeocoderError:
|
||||||
|
# output.speak(_(u"There are no results for the coordinates in this tweet"))
|
||||||
|
except ValueError:
|
||||||
|
output.speak(_(u"Error decoding coordinates. Try again later."))
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def ocr_image(self):
|
||||||
|
tweet = self.get_tweet()
|
||||||
|
media_list = []
|
||||||
|
if hasattr(tweet, "entities") and tweet.entities.get("media") != None:
|
||||||
|
[media_list.append(i) for i in tweet.entities["media"] if i not in media_list]
|
||||||
|
elif hasattr(tweet, "retweeted_status") and tweet.retweeted_status.get("media") != None:
|
||||||
|
[media_list.append(i) for i in tweet.retweeted_status.entities["media"] if i not in media_list]
|
||||||
|
elif hasattr(tweet, "quoted_status") and tweet.quoted_status.entities.get("media") != None:
|
||||||
|
[media_list.append(i) for i in tweet.quoted_status.entities["media"] if i not in media_list]
|
||||||
|
if len(media_list) > 1:
|
||||||
|
image_list = [_(u"Picture {0}").format(i,) for i in range(0, len(media_list))]
|
||||||
|
dialog = dialogs.urlList.urlList(title=_(u"Select the picture"))
|
||||||
|
if dialog.get_response() == widgetUtils.OK:
|
||||||
|
img = media_list[dialog.get_item()]
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
elif len(media_list) == 1:
|
||||||
|
img = media_list[0]
|
||||||
|
else:
|
||||||
|
output.speak(_(u"Invalid buffer"))
|
||||||
|
return
|
||||||
|
if self.session.settings["mysc"]["ocr_language"] != "":
|
||||||
|
ocr_lang = self.session.settings["mysc"]["ocr_language"]
|
||||||
|
else:
|
||||||
|
ocr_lang = ocr.OCRSpace.short_langs.index(tweet.lang)
|
||||||
|
ocr_lang = ocr.OCRSpace.OcrLangs[ocr_lang]
|
||||||
|
api = ocr.OCRSpace.OCRSpaceAPI()
|
||||||
|
try:
|
||||||
|
text = api.OCR_URL(img["media_url"], lang=ocr_lang)
|
||||||
|
except ocr.OCRSpace.APIError as er:
|
||||||
|
output.speak(_(u"Unable to extract text"))
|
||||||
|
return
|
||||||
|
msg = messages.viewTweet(text["ParsedText"], [], False)
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import platform
|
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import arrow
|
import arrow
|
||||||
import webbrowser
|
import webbrowser
|
||||||
@@ -7,11 +6,12 @@ import output
|
|||||||
import config
|
import config
|
||||||
import languageHandler
|
import languageHandler
|
||||||
import logging
|
import logging
|
||||||
from controller import messages
|
from sessions.twitter import compose, utils, templates
|
||||||
from sessions.twitter import compose, utils
|
|
||||||
from mysc.thread_utils import call_threaded
|
from mysc.thread_utils import call_threaded
|
||||||
from tweepy.error import TweepError
|
from tweepy.errors import TweepyException
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
|
from wxUI import commonMessageDialogs
|
||||||
|
from controller.twitter import messages
|
||||||
from . import base
|
from . import base
|
||||||
|
|
||||||
log = logging.getLogger("controller.buffers.twitter.dmBuffer")
|
log = logging.getLogger("controller.buffers.twitter.dmBuffer")
|
||||||
@@ -40,8 +40,8 @@ class DirectMessagesBuffer(base.BaseBuffer):
|
|||||||
results = [i for i in items]
|
results = [i for i in items]
|
||||||
items = results
|
items = results
|
||||||
log.debug("Retrieved %d items for cursored search in function %s" % (len(items), self.function))
|
log.debug("Retrieved %d items for cursored search in function %s" % (len(items), self.function))
|
||||||
except TweepError as e:
|
except TweepyException as e:
|
||||||
log.error("Error %s: %s" % (e.api_code, e.reason))
|
log.exception("Error %s" % (str(e)))
|
||||||
return
|
return
|
||||||
if items == None:
|
if items == None:
|
||||||
return
|
return
|
||||||
@@ -69,7 +69,7 @@ class DirectMessagesBuffer(base.BaseBuffer):
|
|||||||
self.session.db["sent_direct_messages"] = sent_dms
|
self.session.db["sent_direct_messages"] = sent_dms
|
||||||
user_ids = [item.message_create["sender_id"] for item in items]
|
user_ids = [item.message_create["sender_id"] for item in items]
|
||||||
self.session.save_users(user_ids)
|
self.session.save_users(user_ids)
|
||||||
pub.sendMessage("more-sent-dms", data=sent, account=self.session.db["user_name"])
|
pub.sendMessage("twitter.more_sent_dms", data=sent, account=self.session.db["user_name"])
|
||||||
selected = self.buffer.list.get_selected()
|
selected = self.buffer.list.get_selected()
|
||||||
if self.session.settings["general"]["reverse_timelines"] == True:
|
if self.session.settings["general"]["reverse_timelines"] == True:
|
||||||
for i in received:
|
for i in received:
|
||||||
@@ -89,22 +89,16 @@ class DirectMessagesBuffer(base.BaseBuffer):
|
|||||||
def reply(self, *args, **kwargs):
|
def reply(self, *args, **kwargs):
|
||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
screen_name = self.session.get_user(tweet.message_create["sender_id"]).screen_name
|
screen_name = self.session.get_user(tweet.message_create["sender_id"]).screen_name
|
||||||
message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,])
|
message = messages.reply(session=self.session, title=_("Mention"), caption=_("Mention to %s") % (screen_name,), text="@%s " % (screen_name,), thread_mode=False, users=[screen_name,])
|
||||||
if message.message.get_response() == widgetUtils.OK:
|
if message.message.ShowModal() == widgetUtils.OK:
|
||||||
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
tweet_data = message.get_tweet_data()
|
||||||
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
|
call_threaded(self.session.send_tweet, tweet_data)
|
||||||
config.app.write()
|
if hasattr(message.message, "destroy"):
|
||||||
if message.image == None:
|
message.message.destroy()
|
||||||
item = self.session.api_call(call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text(), tweet_mode="extended")
|
|
||||||
if item != None:
|
|
||||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
|
||||||
else:
|
|
||||||
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file)
|
|
||||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
|
||||||
|
|
||||||
def onFocus(self, *args, **kwargs):
|
def onFocus(self, *args, **kwargs):
|
||||||
tweet = self.get_tweet()
|
tweet = self.get_tweet()
|
||||||
if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True:
|
if self.session.settings["general"]["relative_times"] == True:
|
||||||
# fix this:
|
# fix this:
|
||||||
original_date = arrow.get(int(tweet.created_timestamp))
|
original_date = arrow.get(int(tweet.created_timestamp))
|
||||||
ts = original_date.humanize(locale=languageHandler.getLanguage())
|
ts = original_date.humanize(locale=languageHandler.getLanguage())
|
||||||
@@ -134,6 +128,12 @@ class DirectMessagesBuffer(base.BaseBuffer):
|
|||||||
def open_in_browser(self, *args, **kwargs):
|
def open_in_browser(self, *args, **kwargs):
|
||||||
output.speak(_(u"This action is not supported in the buffer yet."))
|
output.speak(_(u"This action is not supported in the buffer yet."))
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
template = self.session.settings["templates"]["dm"]
|
||||||
|
dm = self.get_right_tweet()
|
||||||
|
t = templates.render_dm(dm, template, self.session, relative_times=self.session.settings["general"]["relative_times"], offset_seconds=self.session.db["utc_offset"])
|
||||||
|
return t
|
||||||
|
|
||||||
class SentDirectMessagesBuffer(DirectMessagesBuffer):
|
class SentDirectMessagesBuffer(DirectMessagesBuffer):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@@ -155,4 +155,17 @@ class SentDirectMessagesBuffer(DirectMessagesBuffer):
|
|||||||
else:
|
else:
|
||||||
for i in items:
|
for i in items:
|
||||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
|
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
|
||||||
self.buffer.list.insert_item(False, *tweet)
|
self.buffer.list.insert_item(False, *tweet)
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
template = self.session.settings["templates"]["dm_sent"]
|
||||||
|
dm = self.get_right_tweet()
|
||||||
|
t = templates.render_dm(dm, template, self.session, relative_times=self.session.settings["general"]["relative_times"], offset_seconds=self.session.db["utc_offset"])
|
||||||
|
return t
|
||||||
|
|
||||||
|
def view_item(self):
|
||||||
|
non_tweet = self.get_formatted_message()
|
||||||
|
item = self.get_right_tweet()
|
||||||
|
original_date = arrow.get(int(item.created_timestamp))
|
||||||
|
date = original_date.shift(seconds=self.session.db["utc_offset"]).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||||
|
msg = messages.viewTweet(non_tweet, [], False, date=date)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user