├── .gitignore ├── .gitmodules ├── .travis.yml ├── CHANGELOG ├── LICENSE ├── LICENSE.h ├── Makefile.in ├── Makefile.tgl ├── Makefile.tl-parser ├── README-Cygwin.md ├── README-LUA ├── README-PY.md ├── README.es ├── README.md ├── ax_lua.m4 ├── ax_python.m4 ├── bootstrap ├── compile_osx.sh ├── config.h.in ├── config.sample ├── configure ├── configure.ac ├── debian ├── changelog ├── clean ├── compat ├── control ├── copyright ├── docs ├── install ├── rules ├── source │ └── format ├── telegram-cli.8 ├── telegram-cli.logrotate ├── telegram-cli.manpages ├── telegram-cli.postinst.debhelper ├── telegram-cli.preinst ├── telegram-cli.preinst.debhelper ├── telegram-cli.prerm ├── telegram-cli.prerm.debhelper ├── telegram-cli.upstart └── watch ├── event-old.h ├── gentoo └── net-im │ └── telegram-cli │ ├── Manifest │ └── telegram-cli-9999.ebuild ├── interface.c ├── interface.h ├── json-tg.c ├── json-tg.h ├── loop.c ├── loop.h ├── lua-tg.c ├── lua-tg.h ├── m4-ax_gcc_builtin.m4 ├── m4_ax_check_openssl.m4 ├── m4_ax_check_zlib.m4 ├── main.c ├── mime.types ├── parts └── plugins │ └── x-autotools.py ├── python-tg.c ├── python-tg.h ├── python-types.c ├── python-types.h ├── rpm ├── README.md ├── SPECS │ └── telegram-cli.spec ├── clean └── telegram-cli-build-rpm ├── server.pub ├── snapcraft.yaml ├── start-telegram-daemon ├── telegram-cli-cygwin.patch ├── telegram-daemon ├── telegram.1 ├── telegram.h ├── test.lua ├── tg-server.pub └── tg-test.py /.gitignore: -------------------------------------------------------------------------------- 1 | telegram 2 | *.o 3 | Makefile 4 | aclocal.m4 5 | autom4te.cache 6 | config.h 7 | config.log 8 | config.status 9 | .idea/ 10 | nbproject/ 11 | bin/ 12 | objs/ 13 | dep/ 14 | auto/ 15 | libs/ 16 | debian/telegram-cli.[a-z] 17 | debian/files 18 | debian/telegram-cli/* 19 | debian/telegram-cli.debhelper.log 20 | debian/telegram-cli.substvars 21 | __pycache__ 22 | rpm/BUILD 23 | rpm/BUILDROOT 24 | rpm/RPMS 25 | rpm/SRPMS 26 | rpm/SOURCES 27 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "tgl"] 2 | path = tgl 3 | url = https://github.com/kenorb-contrib/tgl.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | 3 | compiler: 4 | - gcc 5 | - clang 6 | 7 | addons: 8 | apt: 9 | packages: 10 | - libconfig8-dev 11 | - libreadline6-dev 12 | - libssl-dev 13 | - liblua5.2-dev 14 | - lua5.2 15 | - python-dev 16 | - python 17 | - libevent-dev 18 | - libjansson-dev 19 | 20 | sudo: false 21 | 22 | git: 23 | depth: 10 24 | 25 | script: 26 | - git submodule update --init --recursive 27 | - ./configure 28 | - make -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 1.3.4 2 | * set config directory with key -X 3 | * TGL-2.0.3 4 | 5 | 1.3.3 6 | * support for sending custom keyboard 7 | * fixed contact_search 8 | * TGL-2.0.3 9 | 1.3.2 10 | * use TGL-2.0.2 11 | * add block/unblock user methods 12 | * support for autocomplete for bot's commands 13 | 1.3.1 14 | * added error codes 15 | 1.3.0 16 | * layer 28 support (passwords, replies, webpages, other changes) 17 | * output in json format 18 | * support for lua functions in CLI mode (register_interface_function) 19 | * bugfixes 20 | * output error codes to socket 21 | * allow [reply=], [disable_preview] and [enable_preview] prefixes to query 22 | 1.2.1 23 | * fixed registration/login problem 24 | * added extension to downloads 25 | 1.2.0 26 | * layer 22 support 27 | * new authorization code 28 | * fixed time-related problems 29 | * fixed crash after hibernation 30 | 1.0.6 31 | * layer 18 support 32 | 1.0.5 33 | * listening socket (tcp and unix) for commands 34 | 1.0.4 35 | * changed create_group_chat format 36 | * changed search query 37 | * rewritten interface code. Support for escaped characters in quotes 38 | 1.0.3 39 | * options to help to run telegram-cli as daemon 40 | 1.0.2 41 | * Bug fixes 42 | 1.0.1 43 | * Added pfs support. To use it you should add 'pfs_enabled=true' line to config. 44 | * Added export_card/import_card methods 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /LICENSE.h: -------------------------------------------------------------------------------- 1 | " GNU GENERAL PUBLIC LICENSE\n" 2 | " Version 2, June 1991\n" 3 | "\n" 4 | " Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n" 5 | " 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" 6 | " Everyone is permitted to copy and distribute verbatim copies\n" 7 | " of this license document, but changing it is not allowed.\n" 8 | "\n" 9 | " Preamble\n" 10 | "\n" 11 | " The licenses for most software are designed to take away your\n" 12 | "freedom to share and change it. By contrast, the GNU General Public\n" 13 | "License is intended to guarantee your freedom to share and change free\n" 14 | "software--to make sure the software is free for all its users. This\n" 15 | "General Public License applies to most of the Free Software\n" 16 | "Foundation's software and to any other program whose authors commit to\n" 17 | "using it. (Some other Free Software Foundation software is covered by\n" 18 | "the GNU Lesser General Public License instead.) You can apply it to\n" 19 | "your programs, too.\n" 20 | "\n" 21 | " When we speak of free software, we are referring to freedom, not\n" 22 | "price. Our General Public Licenses are designed to make sure that you\n" 23 | "have the freedom to distribute copies of free software (and charge for\n" 24 | "this service if you wish), that you receive source code or can get it\n" 25 | "if you want it, that you can change the software or use pieces of it\n" 26 | "in new free programs; and that you know you can do these things.\n" 27 | "\n" 28 | " To protect your rights, we need to make restrictions that forbid\n" 29 | "anyone to deny you these rights or to ask you to surrender the rights.\n" 30 | "These restrictions translate to certain responsibilities for you if you\n" 31 | "distribute copies of the software, or if you modify it.\n" 32 | "\n" 33 | " For example, if you distribute copies of such a program, whether\n" 34 | "gratis or for a fee, you must give the recipients all the rights that\n" 35 | "you have. You must make sure that they, too, receive or can get the\n" 36 | "source code. And you must show them these terms so they know their\n" 37 | "rights.\n" 38 | "\n" 39 | " We protect your rights with two steps: (1) copyright the software, and\n" 40 | "(2) offer you this license which gives you legal permission to copy,\n" 41 | "distribute and/or modify the software.\n" 42 | "\n" 43 | " Also, for each author's protection and ours, we want to make certain\n" 44 | "that everyone understands that there is no warranty for this free\n" 45 | "software. If the software is modified by someone else and passed on, we\n" 46 | "want its recipients to know that what they have is not the original, so\n" 47 | "that any problems introduced by others will not reflect on the original\n" 48 | "authors' reputations.\n" 49 | "\n" 50 | " Finally, any free program is threatened constantly by software\n" 51 | "patents. We wish to avoid the danger that redistributors of a free\n" 52 | "program will individually obtain patent licenses, in effect making the\n" 53 | "program proprietary. To prevent this, we have made it clear that any\n" 54 | "patent must be licensed for everyone's free use or not licensed at all.\n" 55 | "\n" 56 | " The precise terms and conditions for copying, distribution and\n" 57 | "modification follow.\n" 58 | "\n" 59 | " GNU GENERAL PUBLIC LICENSE\n" 60 | " TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n" 61 | "\n" 62 | " 0. This License applies to any program or other work which contains\n" 63 | "a notice placed by the copyright holder saying it may be distributed\n" 64 | "under the terms of this General Public License. The \"Program\", below,\n" 65 | "refers to any such program or work, and a \"work based on the Program\"\n" 66 | "means either the Program or any derivative work under copyright law:\n" 67 | "that is to say, a work containing the Program or a portion of it,\n" 68 | "either verbatim or with modifications and/or translated into another\n" 69 | "language. (Hereinafter, translation is included without limitation in\n" 70 | "the term \"modification\".) Each licensee is addressed as \"you\".\n" 71 | "\n" 72 | "Activities other than copying, distribution and modification are not\n" 73 | "covered by this License; they are outside its scope. The act of\n" 74 | "running the Program is not restricted, and the output from the Program\n" 75 | "is covered only if its contents constitute a work based on the\n" 76 | "Program (independent of having been made by running the Program).\n" 77 | "Whether that is true depends on what the Program does.\n" 78 | "\n" 79 | " 1. You may copy and distribute verbatim copies of the Program's\n" 80 | "source code as you receive it, in any medium, provided that you\n" 81 | "conspicuously and appropriately publish on each copy an appropriate\n" 82 | "copyright notice and disclaimer of warranty; keep intact all the\n" 83 | "notices that refer to this License and to the absence of any warranty;\n" 84 | "and give any other recipients of the Program a copy of this License\n" 85 | "along with the Program.\n" 86 | "\n" 87 | "You may charge a fee for the physical act of transferring a copy, and\n" 88 | "you may at your option offer warranty protection in exchange for a fee.\n" 89 | "\n" 90 | " 2. You may modify your copy or copies of the Program or any portion\n" 91 | "of it, thus forming a work based on the Program, and copy and\n" 92 | "distribute such modifications or work under the terms of Section 1\n" 93 | "above, provided that you also meet all of these conditions:\n" 94 | "\n" 95 | " a) You must cause the modified files to carry prominent notices\n" 96 | " stating that you changed the files and the date of any change.\n" 97 | "\n" 98 | " b) You must cause any work that you distribute or publish, that in\n" 99 | " whole or in part contains or is derived from the Program or any\n" 100 | " part thereof, to be licensed as a whole at no charge to all third\n" 101 | " parties under the terms of this License.\n" 102 | "\n" 103 | " c) If the modified program normally reads commands interactively\n" 104 | " when run, you must cause it, when started running for such\n" 105 | " interactive use in the most ordinary way, to print or display an\n" 106 | " announcement including an appropriate copyright notice and a\n" 107 | " notice that there is no warranty (or else, saying that you provide\n" 108 | " a warranty) and that users may redistribute the program under\n" 109 | " these conditions, and telling the user how to view a copy of this\n" 110 | " License. (Exception: if the Program itself is interactive but\n" 111 | " does not normally print such an announcement, your work based on\n" 112 | " the Program is not required to print an announcement.)\n" 113 | "\n" 114 | "These requirements apply to the modified work as a whole. If\n" 115 | "identifiable sections of that work are not derived from the Program,\n" 116 | "and can be reasonably considered independent and separate works in\n" 117 | "themselves, then this License, and its terms, do not apply to those\n" 118 | "sections when you distribute them as separate works. But when you\n" 119 | "distribute the same sections as part of a whole which is a work based\n" 120 | "on the Program, the distribution of the whole must be on the terms of\n" 121 | "this License, whose permissions for other licensees extend to the\n" 122 | "entire whole, and thus to each and every part regardless of who wrote it.\n" 123 | "\n" 124 | "Thus, it is not the intent of this section to claim rights or contest\n" 125 | "your rights to work written entirely by you; rather, the intent is to\n" 126 | "exercise the right to control the distribution of derivative or\n" 127 | "collective works based on the Program.\n" 128 | "\n" 129 | "In addition, mere aggregation of another work not based on the Program\n" 130 | "with the Program (or with a work based on the Program) on a volume of\n" 131 | "a storage or distribution medium does not bring the other work under\n" 132 | "the scope of this License.\n" 133 | "\n" 134 | " 3. You may copy and distribute the Program (or a work based on it,\n" 135 | "under Section 2) in object code or executable form under the terms of\n" 136 | "Sections 1 and 2 above provided that you also do one of the following:\n" 137 | "\n" 138 | " a) Accompany it with the complete corresponding machine-readable\n" 139 | " source code, which must be distributed under the terms of Sections\n" 140 | " 1 and 2 above on a medium customarily used for software interchange; or,\n" 141 | "\n" 142 | " b) Accompany it with a written offer, valid for at least three\n" 143 | " years, to give any third party, for a charge no more than your\n" 144 | " cost of physically performing source distribution, a complete\n" 145 | " machine-readable copy of the corresponding source code, to be\n" 146 | " distributed under the terms of Sections 1 and 2 above on a medium\n" 147 | " customarily used for software interchange; or,\n" 148 | "\n" 149 | " c) Accompany it with the information you received as to the offer\n" 150 | " to distribute corresponding source code. (This alternative is\n" 151 | " allowed only for noncommercial distribution and only if you\n" 152 | " received the program in object code or executable form with such\n" 153 | " an offer, in accord with Subsection b above.)\n" 154 | "\n" 155 | "The source code for a work means the preferred form of the work for\n" 156 | "making modifications to it. For an executable work, complete source\n" 157 | "code means all the source code for all modules it contains, plus any\n" 158 | "associated interface definition files, plus the scripts used to\n" 159 | "control compilation and installation of the executable. However, as a\n" 160 | "special exception, the source code distributed need not include\n" 161 | "anything that is normally distributed (in either source or binary\n" 162 | "form) with the major components (compiler, kernel, and so on) of the\n" 163 | "operating system on which the executable runs, unless that component\n" 164 | "itself accompanies the executable.\n" 165 | "\n" 166 | "If distribution of executable or object code is made by offering\n" 167 | "access to copy from a designated place, then offering equivalent\n" 168 | "access to copy the source code from the same place counts as\n" 169 | "distribution of the source code, even though third parties are not\n" 170 | "compelled to copy the source along with the object code.\n" 171 | "\n" 172 | " 4. You may not copy, modify, sublicense, or distribute the Program\n" 173 | "except as expressly provided under this License. Any attempt\n" 174 | "otherwise to copy, modify, sublicense or distribute the Program is\n" 175 | "void, and will automatically terminate your rights under this License.\n" 176 | "However, parties who have received copies, or rights, from you under\n" 177 | "this License will not have their licenses terminated so long as such\n" 178 | "parties remain in full compliance.\n" 179 | "\n" 180 | " 5. You are not required to accept this License, since you have not\n" 181 | "signed it. However, nothing else grants you permission to modify or\n" 182 | "distribute the Program or its derivative works. These actions are\n" 183 | "prohibited by law if you do not accept this License. Therefore, by\n" 184 | "modifying or distributing the Program (or any work based on the\n" 185 | "Program), you indicate your acceptance of this License to do so, and\n" 186 | "all its terms and conditions for copying, distributing or modifying\n" 187 | "the Program or works based on it.\n" 188 | "\n" 189 | " 6. Each time you redistribute the Program (or any work based on the\n" 190 | "Program), the recipient automatically receives a license from the\n" 191 | "original licensor to copy, distribute or modify the Program subject to\n" 192 | "these terms and conditions. You may not impose any further\n" 193 | "restrictions on the recipients' exercise of the rights granted herein.\n" 194 | "You are not responsible for enforcing compliance by third parties to\n" 195 | "this License.\n" 196 | "\n" 197 | " 7. If, as a consequence of a court judgment or allegation of patent\n" 198 | "infringement or for any other reason (not limited to patent issues),\n" 199 | "conditions are imposed on you (whether by court order, agreement or\n" 200 | "otherwise) that contradict the conditions of this License, they do not\n" 201 | "excuse you from the conditions of this License. If you cannot\n" 202 | "distribute so as to satisfy simultaneously your obligations under this\n" 203 | "License and any other pertinent obligations, then as a consequence you\n" 204 | "may not distribute the Program at all. For example, if a patent\n" 205 | "license would not permit royalty-free redistribution of the Program by\n" 206 | "all those who receive copies directly or indirectly through you, then\n" 207 | "the only way you could satisfy both it and this License would be to\n" 208 | "refrain entirely from distribution of the Program.\n" 209 | "\n" 210 | "If any portion of this section is held invalid or unenforceable under\n" 211 | "any particular circumstance, the balance of the section is intended to\n" 212 | "apply and the section as a whole is intended to apply in other\n" 213 | "circumstances.\n" 214 | "\n" 215 | "It is not the purpose of this section to induce you to infringe any\n" 216 | "patents or other property right claims or to contest validity of any\n" 217 | "such claims; this section has the sole purpose of protecting the\n" 218 | "integrity of the free software distribution system, which is\n" 219 | "implemented by public license practices. Many people have made\n" 220 | "generous contributions to the wide range of software distributed\n" 221 | "through that system in reliance on consistent application of that\n" 222 | "system; it is up to the author/donor to decide if he or she is willing\n" 223 | "to distribute software through any other system and a licensee cannot\n" 224 | "impose that choice.\n" 225 | "\n" 226 | "This section is intended to make thoroughly clear what is believed to\n" 227 | "be a consequence of the rest of this License.\n" 228 | "\n" 229 | " 8. If the distribution and/or use of the Program is restricted in\n" 230 | "certain countries either by patents or by copyrighted interfaces, the\n" 231 | "original copyright holder who places the Program under this License\n" 232 | "may add an explicit geographical distribution limitation excluding\n" 233 | "those countries, so that distribution is permitted only in or among\n" 234 | "countries not thus excluded. In such case, this License incorporates\n" 235 | "the limitation as if written in the body of this License.\n" 236 | "\n" 237 | " 9. The Free Software Foundation may publish revised and/or new versions\n" 238 | "of the General Public License from time to time. Such new versions will\n" 239 | "be similar in spirit to the present version, but may differ in detail to\n" 240 | "address new problems or concerns.\n" 241 | "\n" 242 | "Each version is given a distinguishing version number. If the Program\n" 243 | "specifies a version number of this License which applies to it and \"any\n" 244 | "later version\", you have the option of following the terms and conditions\n" 245 | "either of that version or of any later version published by the Free\n" 246 | "Software Foundation. If the Program does not specify a version number of\n" 247 | "this License, you may choose any version ever published by the Free Software\n" 248 | "Foundation.\n" 249 | "\n" 250 | " 10. If you wish to incorporate parts of the Program into other free\n" 251 | "programs whose distribution conditions are different, write to the author\n" 252 | "to ask for permission. For software which is copyrighted by the Free\n" 253 | "Software Foundation, write to the Free Software Foundation; we sometimes\n" 254 | "make exceptions for this. Our decision will be guided by the two goals\n" 255 | "of preserving the free status of all derivatives of our free software and\n" 256 | "of promoting the sharing and reuse of software generally.\n" 257 | "\n" 258 | " NO WARRANTY\n" 259 | "\n" 260 | " 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n" 261 | "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n" 262 | "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n" 263 | "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n" 264 | "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n" 265 | "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n" 266 | "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n" 267 | "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n" 268 | "REPAIR OR CORRECTION.\n" 269 | "\n" 270 | " 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n" 271 | "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n" 272 | "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n" 273 | "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n" 274 | "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n" 275 | "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n" 276 | "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n" 277 | "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n" 278 | "POSSIBILITY OF SUCH DAMAGES.\n" 279 | "\n" 280 | " END OF TERMS AND CONDITIONS\n" 281 | "\n" 282 | " How to Apply These Terms to Your New Programs\n" 283 | "\n" 284 | " If you develop a new program, and you want it to be of the greatest\n" 285 | "possible use to the public, the best way to achieve this is to make it\n" 286 | "free software which everyone can redistribute and change under these terms.\n" 287 | "\n" 288 | " To do so, attach the following notices to the program. It is safest\n" 289 | "to attach them to the start of each source file to most effectively\n" 290 | "convey the exclusion of warranty; and each file should have at least\n" 291 | "the \"copyright\" line and a pointer to where the full notice is found.\n" 292 | "\n" 293 | " \n" 294 | " Copyright (C) \n" 295 | "\n" 296 | " This program is free software; you can redistribute it and/or modify\n" 297 | " it under the terms of the GNU General Public License as published by\n" 298 | " the Free Software Foundation; either version 2 of the License, or\n" 299 | " (at your option) any later version.\n" 300 | "\n" 301 | " This program is distributed in the hope that it will be useful,\n" 302 | " but WITHOUT ANY WARRANTY; without even the implied warranty of\n" 303 | " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" 304 | " GNU General Public License for more details.\n" 305 | "\n" 306 | " You should have received a copy of the GNU General Public License along\n" 307 | " with this program; if not, write to the Free Software Foundation, Inc.,\n" 308 | " 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" 309 | "\n" 310 | "Also add information on how to contact you by electronic and paper mail.\n" 311 | "\n" 312 | "If the program is interactive, make it output a short notice like this\n" 313 | "when it starts in an interactive mode:\n" 314 | "\n" 315 | " Gnomovision version 69, Copyright (C) year name of author\n" 316 | " Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n" 317 | " This is free software, and you are welcome to redistribute it\n" 318 | " under certain conditions; type `show c' for details.\n" 319 | "\n" 320 | "The hypothetical commands `show w' and `show c' should show the appropriate\n" 321 | "parts of the General Public License. Of course, the commands you use may\n" 322 | "be called something other than `show w' and `show c'; they could even be\n" 323 | "mouse-clicks or menu items--whatever suits your program.\n" 324 | "\n" 325 | "You should also get your employer (if you work as a programmer) or your\n" 326 | "school, if any, to sign a \"copyright disclaimer\" for the program, if\n" 327 | "necessary. Here is a sample; alter the names:\n" 328 | "\n" 329 | " Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n" 330 | " `Gnomovision' (which makes passes at compilers) written by James Hacker.\n" 331 | "\n" 332 | " , 1 April 1989\n" 333 | " Ty Coon, President of Vice\n" 334 | "\n" 335 | "This General Public License does not permit incorporating your program into\n" 336 | "proprietary programs. If your program is a subroutine library, you may\n" 337 | "consider it more useful to permit linking proprietary applications with the\n" 338 | "library. If this is what you want to do, use the GNU Lesser General\n" 339 | "Public License instead of this License.\n" 340 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | srcdir=@srcdir@ 2 | 3 | TARGET_OS=$(shell uname -s) 4 | CFLAGS=@CFLAGS@ 5 | LDFLAGS=@LDFLAGS@ @OPENSSL_LDFLAGS@ 6 | CPPFLAGS=@CPPFLAGS@ @OPENSSL_INCLUDES@ 7 | DEFS=@DEFS@ 8 | COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC -Wno-unused-function -Wno-builtin-memcpy-chk-size 9 | EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ @OPENSSL_LIBS@ 10 | LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} -lpthread -lutil 11 | LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} 12 | 13 | ifneq (${TARGET_OS}, FreeBSD) 14 | LOCAL_LDFLAGS += -ldl 15 | endif 16 | 17 | DEP=dep 18 | AUTO=auto 19 | EXE=bin 20 | OBJ=objs 21 | LIB=libs 22 | DIR_LIST=${DEP} ${AUTO} ${EXE} ${OBJ} ${LIB} ${DEP}/auto ${OBJ}/auto ${OBJ}/crypto ${DEP}/crypto 23 | 24 | EXE_LIST=${EXE}/telegram-cli 25 | 26 | TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o ${OBJ}/json-tg.o ${OBJ}/python-tg.o ${OBJ}/python-types.o 27 | 28 | INCLUDE=-I. -I${srcdir} -I${srcdir}/tgl 29 | CC=@CC@ 30 | 31 | PREFIX?=/usr/local 32 | INSTALL_BIN=$(PREFIX)/bin 33 | INSTALL=install 34 | 35 | .SUFFIXES: 36 | 37 | .SUFFIXES: .c .h .o 38 | 39 | all: ${EXE_LIST} ${DIR_LIST} 40 | create_dirs_and_headers: ${DIR_LIST} ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h ${AUTO}/constants.h ${AUTO}/constants.h ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h ${AUTO}/auto-fetch-ds.h ${AUTO}/auto-free-ds.h ${AUTO}/auto-store-ds.h ${AUTO}/auto-print-ds.h 41 | create_dirs: ${DIR_LIST} 42 | dump-tl: ${EXE}/dump-tl-file 43 | 44 | include ${srcdir}/Makefile.tl-parser 45 | include ${srcdir}/Makefile.tgl 46 | 47 | ${DIR_LIST}: 48 | @test -d $@ || mkdir -p $@ 49 | 50 | OBJ_LIST=${TG_OBJECTS} ${TGL_OBJECTS} ${TGL_COMMON_OBJECTS} ${GENERATE_OBJECTS} ${TL_PARSER_OBJECTS} ${TGL_OBJECTS_AUTO} 51 | DEPENDENCE=$(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJ_LIST})) 52 | DEPENDENCE_LIST=${DEPENDENCE} 53 | 54 | -include ${DEPENDENCE_LIST} 55 | 56 | ${TG_OBJECTS}: ${OBJ}/%.o: ${srcdir}/%.c | create_dirs_and_headers 57 | ${CC} ${INCLUDE} ${COMPILE_FLAGS} -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< 58 | 59 | ${EXE}/telegram-cli: ${TG_OBJECTS} ${LIB}/libtgl.a 60 | ${CC} $^ ${LINK_FLAGS} -o $@ 61 | 62 | clean: 63 | rm -rf ${DIR_LIST} 64 | 65 | distclean: 66 | rm -rf ${DIR_LIST} config.h config.log config.status 67 | 68 | install: all 69 | @mkdir -p $(DESTDIR)/$(INSTALL_BIN) 70 | $(INSTALL) bin/telegram-cli $(DESTDIR)/$(INSTALL_BIN) 71 | rm -rf ${DIR_LIST} config.log config.status > /dev/null || echo "all clean" 72 | -------------------------------------------------------------------------------- /Makefile.tgl: -------------------------------------------------------------------------------- 1 | TGL_OBJECTS=${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/mtproto-key.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/tgl.o ${OBJ}/updates.o ${OBJ}/tgl-net.o ${OBJ}/tgl-timers.o ${OBJ}/tg-mime-types.o ${OBJ}/mtproto-utils.o ${OBJ}/crypto/bn_openssl.o ${OBJ}/crypto/bn_altern.o ${OBJ}/crypto/rsa_pem_openssl.o ${OBJ}/crypto/rsa_pem_altern.o ${OBJ}/crypto/md5_openssl.o ${OBJ}/crypto/md5_altern.o ${OBJ}/crypto/sha_openssl.o ${OBJ}/crypto/sha_altern.o ${OBJ}/crypto/aes_openssl.o ${OBJ}/crypto/aes_altern.o 2 | 3 | TGL_OBJECTS_AUTO=${OBJ}/auto/auto-skip.o ${OBJ}/auto/auto-fetch.o ${OBJ}/auto/auto-store.o ${OBJ}/auto/auto-autocomplete.o ${OBJ}/auto/auto-types.o ${OBJ}/auto/auto-fetch-ds.o ${OBJ}/auto/auto-free-ds.o ${OBJ}/auto/auto-store-ds.o ${OBJ}/auto/auto-print-ds.o 4 | 5 | 6 | TLD_OBJECTS=${OBJ}/dump-tl-file.o 7 | GENERATE_OBJECTS=${OBJ}/generate.o 8 | TGL_COMMON_OBJECTS=${OBJ}/tools.o ${OBJ}/crypto/rand_openssl.o ${OBJ}/crypto/rand_altern.o ${OBJ}/crypto/err_openssl.o ${OBJ}/crypto/err_altern.o 9 | TGL_OBJ_C=${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS} 10 | 11 | AR?=ar 12 | 13 | .SUFFIXES: 14 | 15 | .SUFFIXES: .c .h .o 16 | 17 | dump-tl: ${EXE}/dump-tl-file 18 | 19 | ${TGL_OBJECTS}: ${AUTO}/constants.h ${AUTO}/auto-skip.h ${AUTO}/auto-fetch.h ${AUTO}/auto-store.h ${AUTO}/auto-autocomplete.h ${AUTO}/auto-types.h ${AUTO}/auto-fetch-ds.h ${AUTO}/auto-free-ds.h ${AUTO}/auto-store-ds.h ${AUTO}/auto-print-ds.h 20 | 21 | ${TGL_OBJ_C}: ${OBJ}/%.o: ${srcdir}/tgl/%.c | create_dirs 22 | ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< 23 | 24 | ${TGL_OBJECTS_AUTO}: ${OBJ}/auto/%.o: ${AUTO}/%.c | create_dirs 25 | ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< 26 | 27 | #${OBJ}/auto/auto.o: ${AUTO}/auto.c 28 | # ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/auto/auto.d -MQ ${OBJ}/auto/auto.o -o $@ $< 29 | 30 | ${LIB}/libtgl.a: ${TGL_OBJECTS} ${TGL_COMMON_OBJECTS} ${TGL_OBJECTS_AUTO} 31 | rm -f $@ && ${AR} ruv $@ $^ 32 | 33 | ${EXE}/generate: ${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} 34 | ${CC} ${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${LINK_FLAGS} -o $@ 35 | 36 | ${AUTO}/scheme.tlo: ${AUTO}/scheme.tl ${EXE}/tl-parser 37 | ${EXE}/tl-parser -e $@ ${AUTO}/scheme.tl 38 | 39 | ${AUTO}/scheme.tl: ${srcdir}/tgl/scheme.tl ${srcdir}/tgl/encrypted_scheme.tl ${srcdir}/tgl/binlog.tl ${srcdir}/tgl/append.tl ${srcdir}/tgl/mtproto.tl | ${AUTO} 40 | cat $^ > $@ 41 | 42 | ${AUTO}/scheme2.tl: ${AUTO}/scheme.tl ${EXE}/tl-parser 43 | ${EXE}/tl-parser -E ${AUTO}/scheme.tl 2> $@ || ( cat $@ && rm $@ && false ) 44 | 45 | ${AUTO}/auto-%.c: ${AUTO}/scheme.tlo ${EXE}/generate auto/constants.h ${AUTO}/auto-%.h | create_dirs_and_headers 46 | ${EXE}/generate -g $(patsubst ${AUTO}/auto-%.c,%,$@) ${AUTO}/scheme.tlo > $@ || ( rm $@ && false ) 47 | 48 | ${AUTO}/auto-%.h: ${AUTO}/scheme.tlo ${EXE}/generate 49 | ${EXE}/generate -g $(patsubst ${AUTO}/auto-%.h,%-header,$@) ${AUTO}/scheme.tlo > $@ || ( rm $@ && false ) 50 | 51 | ${AUTO}/constants.h: ${AUTO}/scheme2.tl ${srcdir}/tgl/gen_constants_h.awk 52 | awk -f ${srcdir}/tgl/gen_constants_h.awk < $< > $@ 53 | 54 | ${EXE}/dump-tl-file: ${OBJ}/auto/auto.o ${TLD_OBJECTS} 55 | ${CC} ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${LINK_FLAGS} -o $@ 56 | 57 | -------------------------------------------------------------------------------- /Makefile.tl-parser: -------------------------------------------------------------------------------- 1 | TL_PARSER_OBJECTS=${OBJ}/tl-parser.o ${OBJ}/tlc.o 2 | 3 | ${TL_PARSER_OBJECTS}: ${OBJ}/%.o: ${srcdir}/tgl/tl-parser/%.c | create_dirs 4 | ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl/tl-parser -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $< 5 | 6 | ${EXE}/tl-parser: ${TL_PARSER_OBJECTS} 7 | ${CC} $^ ${LINK_FLAGS} -o $@ 8 | -------------------------------------------------------------------------------- /README-Cygwin.md: -------------------------------------------------------------------------------- 1 | ### Installation on Windows 2 | To use telegram-cli in Windows, you should compile with Cygwin which has POSIX API functionality. 3 | 4 | Install [Cygwin](https://www.cygwin.com/). 5 | 6 | In Cygwin Terminal, install cygwin's package manager, apt-cyg, as per apt-cyg's [project page](https://github.com/transcode-open/apt-cyg): 7 | 8 | lynx -source rawgit.com/transcode-open/apt-cyg/master/apt-cyg > apt-cyg 9 | install apt-cyg /bin 10 | 11 | Then install compiler and tools: if you're on the **32-bit** version of cygwin, 12 | 13 | apt-cyg install gcc-core gcc-g++ gcc-core gcc-g++ make wget patch diffutils grep tar gzip autoconf automake libtool git zlib-devel 14 | 15 | Whereas on the **64-bit** version, 16 | 17 | apt-cyg install cygwin32-gcc-core cygwin32-gcc-g++ gcc-core gcc-g++ make wget patch diffutils grep tar gzip zlib-devel 18 | 19 | You need libraries *readline*, *openssl*, *libconfig*, *liblua*, *python* and *libjansson* to use telegram-cli's full functionality. 20 | 21 | Clone this project's GitHub Repository in Cygwin Terminal 22 | 23 | git clone --recursive https://github.com/vysheng/tg.git 24 | 25 | Then type: 26 | 27 | apt-cyg install libevent-devel openssl-devel libreadline-devel lua-devel python3 28 | 29 | (Install package 'python' to use Python 2.7, or install package 'python3' to use Python 3) 30 | 31 | libconfig and libjansson are not included in the cygwin package, so you should compile them yourself. 32 | 33 | Compile libconfig: 34 | 35 | wget https://github.com/hyperrealm/libconfig/archive/v1.7.2.tar.gz 36 | mv v1.7.2.tar.gz libconfig-1.7.2.tar.gz 37 | tar xvf libconfig-1.7.2.tar.gz && cd libconfig-1.7.2 38 | autoreconf 39 | ./configure 40 | make && make install && cd .. 41 | 42 | Compile libjansson: 43 | 44 | wget http://www.digip.org/jansson/releases/jansson-2.7.tar.gz 45 | tar xvf jansson-2.7.tar.gz && cd jansson-2.7 46 | ./configure 47 | make && make install && cd .. 48 | 49 | Then, change to the tg directory and generate the Makefile. 50 | 51 | cd tg 52 | ./configure 53 | 54 | In case `configure` fails, it might be because of the CRLF line endings, so: 55 | 56 | dos2unix -f configure 57 | 58 | And again, 59 | 60 | ./configure 61 | 62 | We need to patch the Makefile and loop.c to compile properly in cygwin. The patch is included, so just type: 63 | 64 | patch -p1 < telegram-cli-cygwin.patch 65 | 66 | Then, 67 | 68 | make 69 | 70 | Once the compilation is complete, **telegram-cli.exe** will be found in the **bin** subdirectory. 71 | 72 | To run `telegram-cli`, type 73 | 74 | bin/telegram-cli -k tg-server.pub 75 | 76 | **Caution**: A binary compiled with Cygwin should be run in Cygwin Terminal. 77 | -------------------------------------------------------------------------------- /README-LUA: -------------------------------------------------------------------------------- 1 | To use lua with client you should write lua script. You can specify it from config ("lua_script" option) or from command_line [-s]. 2 | 3 | It should have several functions: 4 | on_binlog_replay_end() - it is called when replay of old events end. Any updates prior this call were already received by this client 5 | some time ago. 6 | 7 | on_get_difference_end() - it is called after first get_difference call. So we received all updates after last client execute. 8 | 9 | on_our_id(our_id) - Informs about id of currently logged in user. 10 | 11 | on_msg_receive(msg) - it is called when we receive new msg (!! may be called before on_binlog_replay_end, than it is old msg). 12 | on_msg_history(msg) - it is called when a msg from history is printed. 13 | 14 | on_user_update(user,what_changed) - updated info about user. what_changed is array of strings. 15 | on_chat_update(user,what_changed) - updated info about user. what_changed is array of strings. 16 | on_secret_chat_update(user,what_changed) - updated info about user. what_changed is array of strings. 17 | 18 | 19 | 20 | Also, you can call several functions. Each this function last two arguments, are cb_function and cb_extra. 21 | These functions may return false immidiately if something is bad with args, or return true and call cb_function in future. 22 | cb_function would have two or three arguments: first cb_extra, second success (1 or 0), third result (if applicable). 23 | 24 | If you want to pass msg to function, you should pass it's id. 25 | If you want to pass peer to function, you should pass it's print_name. 26 | Or, you can pass string user#id chat#id and secret_chat#id as peer. It is in some cases better. For example if you want to postpone and you are afraid, that print_name would be changed in the meantime. 27 | 28 | Function_list (arguments are listed aside from cb_function and cb_extra, : 29 | get_contact_list () 30 | get_dialog_list () 31 | 32 | rename_chat (chat, new_name) 33 | chat_set_photo (chat, file) 34 | 35 | send_typing (peer) 36 | send_typing_abort (peer) 37 | 38 | send_msg (peer, text) 39 | fwd_msg (peer, msg) 40 | 41 | send_photo (peer, file) 42 | send_video (peer, file) 43 | send_audio (peer, file) 44 | send_document (peer, file) 45 | send_text (peer, file) 46 | 47 | load_photo(msg) 48 | load_video(msg) 49 | load_video_thumb(msg) 50 | load_audio(msg) 51 | load_document(msg) 52 | load_document_thumb(msg) 53 | 54 | chat_info (chat) 55 | channel_info (channel) 56 | user_info (user) 57 | 58 | get_history (peer, limit) 59 | 60 | chat_add_user (chat, user) 61 | chat_del_user (chat, user) 62 | 63 | add_contact (phone, first_name, last_name) 64 | rename_contact (phone, first_name, last_name) 65 | 66 | msg_search (peer, text) 67 | msg_global_search (text) 68 | 69 | mark_read (peer) 70 | 71 | set_profile_photo (file) 72 | 73 | create_secret_chat (user) 74 | create_group_chat (user, name) 75 | 76 | delete_msg (msg) 77 | restore_msg (number) 78 | 79 | status_online () 80 | status_offline () 81 | 82 | send_location (peer, latitude, longitude) 83 | 84 | Also, you have function 85 | postpone (cb_function, cb_extra, timeout). It will call your cb_function in specified number of seconds (number of seconds may be double). 86 | register_interface_function (name, cb_function, cb_arg, description, arg1_type, arg2_type, ...) adds function to CLI interface 87 | -------------------------------------------------------------------------------- /README-PY.md: -------------------------------------------------------------------------------- 1 | Python Bindings 2 | ==================== 3 | All of the functions and methods are executed in the network loop of tg, ***NOT IMMEDIATELY***. What this means is all calls should be considered async, and so there is an optional callback parameter for every function/method as the last parameter. For many uses, you won't care about the return value, so you can leave out the callback. Note there are a few cases where the callback is considered mandatory when the function is considered an information query and has no functionality without returned data. These will explicitly have the callback in the parameter list and will be noted in the description. 4 | 5 | You can specify the python script from config ("python_script" option) or from command_line [-Z]. 6 | 7 | Version Notes 8 | ===================== 9 | The python integration is written with Python 2/3 in mind, however, there is a bias to Python 3. Because of this, there are a few caveats: 10 | - I am only testing against Python 2.7, and have no intention to support/test < 2.7 but am more than happy to accept PRs for fixes as long as it does not break 2.7/3 11 | - repr/print of native types is dumbed down for < 2.7.9, I highly recommend using this version or newer. (This is due to a [bug](http://bugs.python.org/issue22023) in python) 12 | 13 | TGL Callbacks 14 | ============= 15 | Assign python fuctions to the following tgl attributes to set callbacks from TG. 16 | 17 | | Callback | Description | 18 | |--------- | ---------------------| 19 | |`tgl.on_binlog_replay_end()` | This is called when replay of old events end. Any updates prior this call were already received by this client some time ago.| 20 | |`tgl.on_get_difference_end()`| This is called after first get_difference call. So we received all updates after last client execute.| 21 | |`tgl.on_our_id(our_id)`|Informs about id of currently logged in user.| 22 | |`tgl.on_msg_receive(msg)`| This is called when we receive new `tgl.Msg` object (*may be called before on_binlog_replay_end, than it is old msg*).| 23 | |`tgl.on_msg_history(msg)`| This is called when we receive a `tgl.Msg` object from a history printing.| 24 | |`tgl.on_user_update(peer, what_changed)`|updated info about user. peer is a `tgl.Peer` object representing the user, and what_changed is array of strings.| 25 | |`tgl.on_chat_update(peer, what_changed)`|updated info about chat. peer is a `tgl.Peer` object representing the chat, and what_changed is array of strings.| 26 | |`tgl.on_secret_chat_update(peer, what_changed)`|updated info about secret chat. peer is a `tgl.Peer` object representing the secret chat, and what_changed is array of strings.| 27 | |`tgl.on_loop()` | This is called every now and then.| 28 | 29 | Python Callback Signatures 30 | ========================= 31 | As mentioned, all methods and functions have callbacks. The following are the different signatures that may be required (*The description of the method will mention which is used*) 32 | 33 | | Type | Signature | Description | 34 | |----- | ------------------ | ------------| 35 | |empty_cb|`(success)`|This just indicated the success of the call. All other callback types have this as well.| 36 | |contact_list_cb|`(success, peer_list)`|`peer_list` is a list of `tgl.Peer` objects| 37 | |dialog_list_cb|`(success, dialog_list)`|`dialog_list` is a list of dicts, with keys: 'peer': `tgl.Peer`, 'unread': `bool( Determine whether has unread message)`| 38 | |msg_cb|`(success, msg)`|`msg` is a `tgl.Msg`| 39 | |msg_list_cb|`(success, msg_list)`|`msg_list` is a list of `tgl.Msg` objects| 40 | |file_cb|`(success, file_path)`|`file_path` is a string with an absolute path| 41 | |chat_cb|`(success, peer)`|`peer` is a `tgl.Peer` that will have the type of `tgl.PEER_CHAT`| 42 | |peer_cb|`(success, peer)`|`peer` is a `tgl.Peer`| 43 | |secret_chat_cb|`(success, peer)`|`peer` is a `tgl.Peer` that will have the type of `tgl.PEER_ENCR_CHAT`| 44 | |user_cb|`(success, peer)`|`peer` is a `tgl.Peer` that will have the type of `tgl.PEER_USER`| 45 | |str_cb|`(success, string)`|`string` is a simple string| 46 | 47 | TGL Module Level Fuctions 48 | ========================= 49 | All of these functions are accessed by importing the `tgl` module. 50 | 51 | | Function | Description | Callback Type | 52 | |--------- | ---------------------| ------------- | 53 | |`tgl.get_contact_list (callback)`|Retrieve peers stored in the contact list. *requires callback*|`contact_list_cb`| 54 | |`tgl.get_dialog_list (callback)`|Get a list of current conversations with the `tgl.Peer` and the most recent `tgl.Msg`. *requires callback*|`dialog_list_cb`| 55 | |`tgl.add_contact (phone, first_name, last_name)`|Adds contact to contact list, last name is optional|`contact_list_cb`| 56 | |`tgl.del_contact (peer)`|Removes contact from contact list|`empty_cb`| 57 | |`tgl.rename_contact (phone, first_name, last_name) `|Renaming a contact means sending the first/last name with the same phone number of an existing contact|`contact_list_cb`| 58 | |`tgl.msg_global_search (text, callback)`|Get all messages that match the search text. *requires callback*|`msg_list_cb`| 59 | |`tgl.set_profile_photo (file_path)`|Sets avatar to image found at `file_path`, no checking on the file.|`empty_cb`| 60 | |`tgl.create_secret_chat (user)`|Creates secret chat with user, callback recommended to get new peer for the secret chat.|`secret_chat_cb`| 61 | |`tgl.create_group_chat (peer_list, name)`|`peer_list` contains users to create group with, must be more than 1 peer.|`empty_cb`| 62 | |`tgl.delete_msg (msg_id)`|Deletes the message from the local history.|`empty_cb`| 63 | |`tgl.restore_msg (msg_id)`|Restore a deleted message by message id.|`empty_cb`| 64 | |`tgl.status_online ()`|Sets status as online|`empty_cb`| 65 | |`tgl.status_offline ()`|Sets status as offline|`empty_cb`| 66 | |`tgl.import_chat_link (link)`|Join channel using the `link`.|`empty_cb`| 67 | |`tgl.safe_exit (exit_status)`|Exception to the rule about callbacks, no callback parameter is accepted. Causes the bot to quit after cleaning up. `exit_status` is an optional parameter with the exit status (On glibc, this must be 0-255)|NONE| 68 | 69 | Peer 70 | ==== 71 | ## Attributes 72 | | Attribute | Type | Description | 73 | |---------- | ---- | ----------------------| 74 | |`id`|`int`|Telegram peer id| 75 | |`type`|`int`|Peer type, you can compare this with `tgl.PEER_CHAT`, `tgl.PEER_USER`, or `tgl.PEER_ENCR_CHAT`| 76 | |`type_name`|`string`|Text representation of the type of the peer, `'chat'`, `'user'`, or `'secret_chat'`| 77 | |`name`|`string`|Returns the tg print version of the name. Usually `FirstName_LastName` for user, and the chatname with spaces replaced with `_`| 78 | |`user_id`|`int`|Used in secret chats, since a secret chat has it's own id, this is the id of the user at the endpoint.| 79 | |`user_list`|`peer_list`|Only used in `tgl.PEER_CHAT` peers, contains list of users. This currently does not work, it is not populating properly.| 80 | |`user_status`|`dict`|Only used in `tgl.PEER_USER` peers. Dictionary with the current status, keys: 'online': `bool`, 'when': `datetime`| 81 | |`phone`|`string`|Only used in `tgl.PEER_USER` peers. Phone number, only available if user is on contact list.| 82 | |`username`|`string`|Only used in `tgl.PEER_USER` peers. Will be `None` if username is not set.| 83 | |`first_name`|`string`|Only used in `tgl.PEER_USER` peers.| 84 | |`last_name`|`string`|Only used in `tgl.PEER_USER` peers.| 85 | 86 | ## Methods 87 | | Method | Description | Callback Type | 88 | |------- | ---------------------| ------------- | 89 | |`peer.rename_chat (new_name)`||`empty_cb`| 90 | |`peer.chat_set_photo (file)`|Sets avatar for the group to image found at `file_path`, no checking on the file. The calling peer must be of type `tgl.PEER_CHAT`.|`msg_cb`| 91 | |`peer.send_typing ()`|Tell peer that you are typing.|`empty_cb`| 92 | |`peer.send_typing_abort ()`|Tell peer you are done typing.|`empty_cb`| 93 | |`peer.send_msg (text, reply=msg_id, preview=bool)`|Sends message to peer. Optional keyword arguments: reply is the message id we are replying to, preview is a boolean that forces URL preview on or off.|`msg_cb`| 94 | |`peer.fwd_msg (msg_id)`|Forwards msg with message id to peer.|`msg_cb`| 95 | |`peer.fwd_media (msg_id)`|Forwards media with message id to peer.|`msg_cb`| 96 | |`peer.send_photo (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| 97 | |`peer.send_video (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| 98 | |`peer.send_audio (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| 99 | |`peer.send_document (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| 100 | |`peer.send_text (file)`|Send media to peer using `file`. No checking is done on the contents of the file.|`msg_cb`| 101 | |`peer.send_location (latitude, longitude)`|Sends location media message to peer, `longitude` and `latitude` should be specified as double.|`msg_cb`| 102 | |`peer.chat_add_user (user)`|Adds `user`(`tgl.Peer`) to the group. The calling peer must be of type `tgl.PEER_CHAT`|`empty_cb`| 103 | |`peer.chat_del_user (user)`|Removes `user`(`tgl.Peer`) from the group. The calling peer must be of type `tgl.PEER_CHAT`|`empty_cb`| 104 | |`peer.mark_read ()`|Marks the dialog with the peer as read. This cannot be done on message level.|`empty_cb`| 105 | |`peer.msg_search (text, callback)`|Get all messages that match the search text with the peer. *requires callback*|`msg_list_cb`| 106 | |`peer.history (offset, limit, callback)`|Get all messages with the peer. `offset` specifies what message to start at, and `limit` specifies how many messages to retrieve. See example below for one method to get the entire history. *requires callback*|`msg_list_cb`| 107 | |`peer.info ()`|Gets peer info.|`peer_cb`| 108 | 109 | Example usage for `peer.history`: 110 | ``` 111 | from functools import partial 112 | history = [] 113 | # Get all the history, 100 msgs at a time 114 | peer.history(0, 100, partial(history_callback, 100, peer)) 115 | 116 | def history_callback(msg_count, peer, success, msgs): 117 | history.extend(msgs) 118 | if len(msgs) == msg_count: 119 | peer.history(len(history), msg_count, partial(history_callback, msg_count, peer)) 120 | ``` 121 | 122 | Msg 123 | ==== 124 | ## Attributes 125 | | Attribute | Type | Description | 126 | |---------- | ---- | ----------------------| 127 | |`id`|`int`|Message id| 128 | |`flags`|`int`|tgl flags, see source code for tgl for various possible flags. This is a bitfield in an int.| 129 | |`mention`|`bool`|`True` if you are @mentioned.| 130 | |`out`|`bool`|`True` if you sent this message.| 131 | |`unread`|`bool`|`True` if you have not marked this as read.| 132 | |`service`|`bool`|`True` if the message is a service messages, see tgl.Msg.action for the type.| 133 | |`src`|`tgl.Peer`|Peer who sent the message| 134 | |`dest`|`tgl.Peer`|Peer who the message was sent too. In a group, this will be the chat peer. Otherwise it will be you.| 135 | |`text`|`string`|Text contents of the message. This may be `None` if it's media without caption.| 136 | |`media`|`dict`|Dictionary that varies based on the media type.| 137 | |`date`|`datetime`|When the message was sent.| 138 | |`fwd_src`|`tgl.Peer`|The user that sent the forwarded message.| 139 | |`fwd_date`|`datetime`|When the forwarded message was originally sent.| 140 | |`reply`|`tgl.Msg`|Message that this message is replying to.| 141 | |`reply_id`|`int`|Message id that this message is replying to.| 142 | |`action`|`int`|Action enum for the message if `msg.service == True`. See all the possible values below| 143 | 144 | ## Action Type Constants 145 | - tgl.ACTION_NONE 146 | - tgl.ACTION_GEO_CHAT_CREATE 147 | - tgl.ACTION_GEO_CHAT_CHECKIN 148 | - tgl.ACTION_CHAT_CREATE 149 | - tgl.ACTION_CHAT_EDIT_TITLE 150 | - tgl.ACTION_CHAT_EDIT_PHOTO 151 | - tgl.ACTION_CHAT_DELETE_PHOTO 152 | - tgl.ACTION_CHAT_ADD_USER 153 | - tgl.ACTION_CHAT_ADD_USER_BY_LINK 154 | - tgl.ACTION_CHAT_DELETE_USER 155 | - tgl.ACTION_SET_MESSAGE_TTL 156 | - tgl.ACTION_READ_MESSAGES 157 | - tgl.ACTION_DELETE_MESSAGES 158 | - tgl.ACTION_SCREENSHOT_MESSAGES 159 | - tgl.ACTION_FLUSH_HISTORY 160 | - tgl.ACTION_RESEND 161 | - tgl.ACTION_NOTIFY_LAYER 162 | - tgl.ACTION_TYPING 163 | - tgl.ACTION_NOOP 164 | - tgl.ACTION_COMMIT_KEY 165 | - tgl.ACTION_ABORT_KEY 166 | - tgl.ACTION_REQUEST_KEY 167 | - tgl.ACTION_ACCEPT_KEY 168 | 169 | ## Methods 170 | | Method | Description | Callback Type | 171 | |------- | ---------------------| ------------- | 172 | |`msg.load_photo(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| 173 | |`msg.load_video(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| 174 | |`msg.load_video_thumb(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| 175 | |`msg.load_audio(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| 176 | |`msg.load_document(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| 177 | |`msg.load_document_thumb(callback)`|Saves the media and returns the path to the file in the callback. *requires callback*|`file_cb`| 178 | -------------------------------------------------------------------------------- /README.es: -------------------------------------------------------------------------------- 1 | ## Telegram messenger CLI [![Build Status](https://travis-ci.org/kenorb-contrig/tg.png)](https://travis-ci.org/kenorb-contrig/tg) 2 | 3 | !!!! May be outdated. Please refer to english README as more actual. 4 | 5 | 6 | Interfaz de línea de comandos para: [Telegram](http://telegram.org). Usa interfaz readline. 7 | 8 | ### Documentación del API y el protocolo 9 | 10 | La documentación del APi de Telegram está disponible aquí: http://core.telegram.org/api 11 | 12 | La documentación del protocolo MTproto está disponible aquí: http://core.telegram.org/mtproto 13 | 14 | ### Instalación 15 | 16 | Clona el Repositorio GitHub 17 | 18 | $ git clone --recursive https://github.com/kenorb-contrig/tg.git && cd tg 19 | 20 | o descarga y descomprime el zip 21 | 22 | $ wget https://github.com/kenorb-contrig/tg/archive/master.zip -O tg-master.zip 23 | $ unzip tg-master.zip && cd tg-master 24 | 25 | #### Linux 26 | 27 | Librerías requeridas: readline openssl y (si desea usar config) libconfig y liblua. 28 | Si no deseas usarlo, pasa las siguientes opciones --disable-libconfig y --disable-liblua respectivamente. 29 | 30 | En Ubuntu usa: 31 | 32 | $ sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev 33 | 34 | En gentoo: 35 | 36 | $ sudo emerge -av sys-libs/readline dev-libs/libconfig dev-libs/openssl dev-lang/lua 37 | 38 | En Fedora: 39 | 40 | $ sudo yum install lua-devel openssl-devel libconfig-devel readline-devel 41 | 42 | Por defecto Makefile utiliza liblua5.2 de ubuntu. Si utilizas una versión diferente de liblua o linux, tienes que ejecutar el script ./configure o recibirás un error de compilación extraño. 43 | 44 | Entonces 45 | 46 | $ ./configure 47 | $ make 48 | 49 | 50 | #### Mac OS X 51 | 52 | El cliente depende de [librería readline](http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html) y [libconfig](http://www.hyperrealm.com/libconfig/), las cuales no están incluídas en OS X por defecto. Debes instalar estas librerías de forma manual, usando por ejemplo [Homebrew](http://brew.sh/). 53 | 54 | $ brew install libconfig 55 | $ brew install readline 56 | $ brew install lua 57 | $ export CFLAGS="-I/usr/local/include -I/usr/local/Cellar/readline/6.2.4/include" 58 | $ export LDFLAGS="-L/usr/local/lib -L/usr/local/Cellar/readline/6.2.4/lib" 59 | $ ./configure && make 60 | 61 | Gracias a [@jfontan](https://github.com/vysheng/tg/issues/3#issuecomment-28293731) por esta solución. 62 | 63 | #### FreeBSD 64 | 65 | Instalar estos puertos: 66 | 67 | * devel/libconfig 68 | * devel/libexecinfo 69 | 70 | Entonces construir: 71 | 72 | $ env CC=clang CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure 73 | $ make 74 | 75 | #### Otros UNIX 76 | 77 | Si logras ejecutarlo en otros UNIX, por favor házmelo saber. 78 | 79 | 80 | ### Uso 81 | 82 | ./telegram -k 83 | 84 | 85 | Por defecto la clave pública se almacena en la misma carpeta con el nombre tg-server.pub o en /etc/telegram/server.pub, si no lo es, indica dónde encontrarlo: 86 | 87 | ./telegram -k tg-server.pub 88 | 89 | El Cliente soporta completamiento con TAB e historial de comandos. 90 | 91 | Peer se refiere al nombre del contacto o de diálogo y se puede acceder por completamiento con Tab. 92 | Para los contactos de usuario el peer es el Nombre Apellido con todos los espacios cambiados a guiones bajos. 93 | Para los chats es su título con todos los espacios cambiados a guiones bajos. 94 | Para los chats encriptados es Nombre Apellido con todos los espacios cambiados a guiones bajos. 95 | 96 | Si dos o más peers tienen el mismo nombre, una almohadilla y un número es añadido al nombre. (por ejemplo A_B,A_B#1,A_B#2 y así sucesivamente). 97 | 98 | ### Comandos soportados 99 | 100 | #### Mensajería 101 | 102 | 103 | * **msg** \ texto - envía el mensaje a este usuario. 104 | * **fwd** \ \ - reenviar un mensaje al usuario. Puedes ver los número de mensajes iniciando el Cliente con -N. 105 | * **chat_with_peer** \ - inicia un chat con este usuario. /exit o /quit para salir de este modo. 106 | * **add_contact** \ \ \ - intenta añadir este contacto a la lista de contactos. 107 | * **rename_contact** \ \ \ - intenta renombrar el contacto. Si tienes otro dispositivo será una pelea. 108 | * **mark_read** \ - marca todos los mensajes como recibidos de ese usuario. 109 | 110 | #### Multimedia 111 | 112 | * **send_photo** \ \ - manda una foto al usuario. 113 | * **send_video** \ \ - envia un video al usuario. 114 | * **send_text** \ \ - envia un archivo de texto como un mensaje en plano. 115 | * **load_photo**/load_video/load_video_thumb \ - carga foto/video indicado del directorio de descarga. 116 | * **view_photo**/view_video/view_video_thumb \ - carga foto/video indicado del directorio de descarga y lo abre con el visor por defecto del sistema. 117 | 118 | 119 | #### Opciones de chat de grupo 120 | 121 | * **chat_info** \ - imprime información del chat. 122 | * **chat_add_user** \ \ - agrega un usuario al chat. 123 | * **chat_del_user** \ \ - elimina un usuario del chat. 124 | * **rename_chat** \ \ - cambia el nombre al chat. 125 | 126 | #### Search 127 | 128 | * **search** \ patrón - busca el patrón indicado en los mensajes con ese usuario. 129 | * **global_search** patrón - busca el patrón indicado en todos los mensajes. 130 | 131 | #### Chat secreto 132 | 133 | * **create_secret_chat** \ - crea un chat secreto con el usuario indicado. 134 | * **visualize_key** \ - Muestra la clave de cifrado. Debes compararla con la del otro usuario. 135 | 136 | #### Estadísticas e información varia. 137 | 138 | * **user_info** \ - muestra información sobre el usuario. 139 | * **history** \ [limit] - muestra el historial (y la marca como leído). Limite por defecto = 40. 140 | * **dialog_list** - muestra información acerca del dialogo 141 | * **contact_list** - muestra información acerca de tu lista de contactos. 142 | * **suggested_contacts** - muestra información sobre sus contactos, tiene un máximo de amigos comunes. 143 | * **stats** - solo para depuración. 144 | * **show_license** - muestra la licencia GPLv2. 145 | * **help** - imprime esta ayuda. 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Telegram messenger CLI 2 | 3 | Command-line interface for [Telegram](http://telegram.org). Uses readline interface. It is client implementation of TGL library. 4 | 5 | > Note: This is a fork of [`telegram-cli`](https://github.com/vysheng/tg). 6 | 7 | Build status: 8 | 9 | | Repository | Status| 10 | | ------------------------------------------------------ | ----- | 11 | | [vysheng](https://github.com/vysheng/tg) (main) |[![Build Status](https://travis-ci.org/vysheng/tg.png)](https://travis-ci.org/vysheng/tg)| 12 | | [kenorb-contrib](https://github.com/kenorb-contrib/tg) |[![Build Status](https://travis-ci.org/kenorb-contrib/tg.png)](https://travis-ci.org/kenorb-contrib/tg)| 13 | 14 | ### API, Protocol documentation 15 | 16 | Documentation for Telegram API is available here: 17 | 18 | Documentation for MTproto protocol is available here: 19 | 20 | ### Upgrading to version 1.0 21 | 22 | First of all, the binary is now in ./bin folder and is named telegram-cli. So be careful, not to use old binary. 23 | 24 | Second, config folder is now ${HOME}/.telegram-cli 25 | 26 | Third, database is not compatible with older versions, so you'll have to login again. 27 | 28 | Fourth, in `peer_name` '#' are substitued to '@'. (Not applied to appending of '#%d' in case of two peers having same name). 29 | 30 | ### Installation 31 | 32 | Clone this GitHub repository with `--recursive` parameter to clone submodules. 33 | 34 | git clone --recursive https://github.com/kenorb-contrib/tg.git && cd tg 35 | 36 | ### Python Support 37 | 38 | Python support is currently limited to Python 2.7 or Python 3.1+. Other versions may work but are not tested. 39 | 40 | #### Linux and BSDs 41 | 42 | Install libs: readline, openssl and (if you want to use config) libconfig, liblua, python and libjansson. 43 | If you do not want to use them pass options --disable-libconfig, --disable-liblua, --disable-python and --disable-json respectively. 44 | 45 | On Ubuntu/Debian use: 46 | 47 | sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev libpython3-dev libgcrypt-dev zlib1g-dev lua-lgi make 48 | 49 | To build and install the packaege, run: 50 | 51 | dpkg-buildpackage -b 52 | sudo dpkg -i ../telegram-cli_x.x.x-x_amd64.deb 53 | 54 | On Gentoo: 55 | 56 | sudo emerge -av sys-libs/readline dev-libs/libconfig dev-libs/openssl dev-lang/lua dev-libs/libevent dev-libs/jansson dev-lang/python 57 | 58 | On Fedora: 59 | 60 | sudo dnf install lua-devel openssl-devel libconfig-devel readline-devel libevent-devel jansson-devel python-devel libgcrypt-devel 61 | 62 | On CentOS: 63 | 64 | sudo yum install lua-devel openssl-devel libconfig-devel readline-devel libevent-devel jansson-devel python-devel 65 | 66 | On Archlinux: 67 | 68 | yay -S telegram-cli-git 69 | 70 | On Milislinux: 71 | 72 | mps kur telegram-cli 73 | 74 | On FreeBSD: 75 | 76 | pkg install telegram-cli 77 | 78 | On OpenBSD: 79 | 80 | pkg_add libconfig libexecinfo lua python 81 | 82 | On openSUSE: 83 | 84 | sudo zypper in lua-devel libconfig-devel readline-devel libevent-devel libjansson-devel python-devel libopenssl-devel 85 | 86 | Then, 87 | 88 | ./configure 89 | make 90 | 91 | If you are going to build tg on OpenBSD or FreeBSD, please use `gmake` instead of `make`. 92 | 93 | #### Other methods to install on linux 94 | 95 | On Gentoo: use ebuild provided. 96 | 97 | On Arch: https://aur.archlinux.org/packages/telegram-cli-git 98 | 99 | #### Mac OS X 100 | 101 | The client depends on [readline library](http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html) and [libconfig](http://www.hyperrealm.com/libconfig/), which are not included in OS X by default. You have to install these libraries manually. 102 | 103 | If using [Homebrew](http://brew.sh/): 104 | 105 | brew tap ivoputzer/tg 106 | brew install tg 107 | 108 | or manually: 109 | 110 | brew install libconfig readline lua python libevent jansson 111 | export READLINEPATH=$(brew --prefix readline) 112 | export OPENSSLPATH=$(brew --prefix openssl) 113 | export CPPFLAGS="-I/usr/local/opt/openssl/include -I$READLINEPATH/include -W" 114 | export CFLAGS="-I/usr/local/include -I$READLINEPATH/include -I$OPENSSLPATH/include" 115 | export LDFLAGS="-L/usr/local/lib -L$READLINEPATH/lib -L$OPENSSLPATH/lib" 116 | 117 | ./configure 118 | 119 | You might have to manually pass the location of OpenSSL to `configure`: 120 | 121 | $ brew info openssl 122 | openssl: stable 1.0.2e (bottled) [keg-only] 123 | Poured from bottle /usr/local/Cellar/openssl/1.0.2e_1 (465 files, 11.9M) 124 | 125 | so in this case the configure should be run as: 126 | 127 | ./configure --with-openssl=/usr/local/Cellar/openssl/1.0.2e_1 128 | 129 | in other cases OpenSSL could be found in `/usr/local/opt`, e.g.: 130 | 131 | ./configure --with-openssl=/usr/local/opt/openssl 132 | 133 | If you get a LUA error on Sierra, you can configure without LUA using 134 | 135 | ./configure --disable-liblua 136 | 137 | After configuration run build: 138 | 139 | make 140 | 141 | Thanks to [@jfontan](https://github.com/vysheng/tg/issues/3#issuecomment-28293731) for this solution. 142 | 143 | If using [MacPorts](https://www.macports.org): 144 | 145 | sudo port install libconfig-hr 146 | sudo port install readline 147 | sudo port install lua51 148 | sudo port install python34 149 | sudo port install libevent 150 | export CFLAGS="-I/usr/local/include -I/opt/local/include -I/opt/local/include/lua-5.1" 151 | export LDFLAGS="-L/usr/local/lib -L/opt/local/lib -L/opt/local/lib/lua-5.1" 152 | ./configure && make 153 | 154 | #### Docker 155 | 156 | The set for dockerizing the app: https://github.com/semenyukdmitry/telegram_cli_docker. 157 | 158 | #### Other UNIX 159 | 160 | If you manage to launch it on other UNIX, please let me know. 161 | 162 | ### Contacts 163 | If you would like to ask a question, you can write to my telegram or to the github (or both). To contact me via telegram, you should use import_card method with argument 000653bf:0738ca5d:5521fbac:29246815:a27d0cda 164 | 165 | 166 | ### Usage 167 | 168 | bin/telegram-cli -k 169 | 170 | By default, the public key is stored in tg-server.pub in the same folder or in /etc/telegram-cli/server.pub. If not, specify where to find it: 171 | 172 | bin/telegram-cli -k tg-server.pub 173 | 174 | Client support TAB completion and command history. 175 | 176 | Peer refers to the name of the contact or dialog and can be accessed by TAB completion. 177 | For user contacts peer name is Name Lastname with all spaces changed to underscores. 178 | For chats it is it's title with all spaces changed to underscores 179 | For encrypted chats it is Name Lastname with all spaces changed to underscores. 180 | 181 | If two or more peers have same name, number is appended to the name. (for example A_B, A_B#1, A_B#2 and so on) 182 | 183 | ### Supported commands 184 | 185 | #### Messaging 186 | 187 | * **msg** \ Text - sends message to this peer 188 | * **fwd** \ \ - forward message to user. You can see message numbers starting client with -N 189 | * **chat_with_peer** \ starts one on one chat session with this peer. /exit or /quit to end this mode. 190 | * **add_contact** \ \ \ - tries to add contact to contact-list by phone 191 | * **rename_contact** \ \ \ - tries to rename contact. If you have another device it will be a fight 192 | * **mark_read** \ - mark read all received messages with peer 193 | * **delete_msg** \ - deletes message (not completly, though) 194 | * **restore_msg** \ - restores delete message. Impossible for secret chats. Only possible short time (one hour, I think) after deletion 195 | 196 | #### Multimedia 197 | 198 | * **send_photo** \ \ - sends photo to peer 199 | * **send_video** \ \ - sends video to peer 200 | * **send_text** \ \ - sends text file as plain messages 201 | * **send_document** \ \ - sends document to peer 202 | * **load_photo**/load_video/load_video_thumb/load_audio/load_document/load_document_thumb \ - loads photo/video/audio/document to download dir 203 | * **view_photo**/view_video/view_video_thumb/view_audio/view_document/view_document_thumb \ - loads photo/video to download dir and starts system default viewer 204 | * **fwd_media** \ send media in your message. Use this to prevent sharing info about author of media (though, it is possible to determine user_id from media itself, it is not possible get access_hash of this user) 205 | * **set_profile_photo** \ - sets userpic. Photo should be square, or server will cut biggest central square part 206 | 207 | 208 | #### Group chat options 209 | 210 | * **chat_info** \ - prints info about chat 211 | * **chat_add_user** \ \ - add user to chat 212 | * **chat_del_user** \ \ - remove user from chat 213 | * **rename_chat** \ \ 214 | * **create_group_chat** \ \ \ \ ... - creates a groupchat with users, use chat_add_user to add more users 215 | * **chat_set_photo** \ \ - sets group chat photo. Same limits as for profile photos. 216 | 217 | ### Channels 218 | 219 | * **channel_get_admins** \ [limit=100] [offset=0] - Gets channel admins 220 | * **channel_get_members** \ [limit=100] [offset=0] - Gets channel members 221 | * **channel_info** \ - Prints info about channel (id, members, admin, etc.) 222 | * **channel_invite** \ \ - Invites user to channel 223 | * **channel_join** \ - Joins to channel 224 | * **channel_kick** \ \ - Kicks user from channel 225 | * **channel_leave** \ - Leaves from channel 226 | * **channel_list** [limit=100] [offset=0] - List of last channels 227 | * **channel_set_about** \ \ - Sets channel about info. 228 | * **channel_set_admin** \ \ \ - Sets channel admin. 0 - not admin, 1 - moderator, 2 - editor 229 | * **channel_set_photo** \ \ - Sets channel photo. Photo will be cropped to square 230 | * **channel_set_username** \ \ -Sets channel username info. 231 | 232 | #### Search 233 | 234 | * **search** \ pattern - searches pattern in messages with peer 235 | * **global_search** pattern - searches pattern in all messages 236 | 237 | #### Secret chat 238 | 239 | * **create_secret_chat** \ - creates secret chat with this user 240 | * **visualize_key** \ - prints visualization of encryption key. You should compare it to your partner's one 241 | * **set_ttl** \ \ - sets ttl to secret chat. Though client does ignore it, client on other end can make use of it 242 | * **accept_secret_chat** \ - manually accept secret chat (only useful when starting with -E key) 243 | 244 | #### Stats and various info 245 | 246 | * **user_info** \ - prints info about user 247 | * **history** \ [limit] - prints history (and marks it as read). Default limit = 40 248 | * **dialog_list** - prints info about your dialogs 249 | * **contact_list** - prints info about users in your contact list 250 | * **suggested_contacts** - print info about contacts, you have max common friends 251 | * **stats** - just for debugging 252 | * **show_license** - prints contents of GPLv2 253 | * **help** - prints this help 254 | * **get_self** - get our user info 255 | 256 | #### Card 257 | * **export_card** - print your 'card' that anyone can later use to import your contact 258 | * **import_card** \ - gets user by card. You can write messages to him after that. 259 | 260 | #### Other 261 | * **quit** - quit 262 | * **safe_quit** - wait for all queries to end then quit 263 | * run `telegram-cli -q` to logout from account 264 | 265 | #### Troubleshooting 266 | * if you got error: `get error FAIL: 38: can not parse arg #1` it maybe be unresolved username. You should use `resolve_username channel/group/user_name` before running action with it. [See this issue for more info](https://github.com/vysheng/tg/issues/823) 267 | -------------------------------------------------------------------------------- /ax_python.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_python.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_PYTHON 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro does a complete Python development environment check. 12 | # 13 | # It recurses through several python versions (from 2.1 to 2.6 in this 14 | # version), looking for an executable. When it finds an executable, it 15 | # looks to find the header files and library. 16 | # 17 | # It sets PYTHON_BIN to the name of the python executable, 18 | # PYTHON_INCLUDE_DIR to the directory holding the header files, and 19 | # PYTHON_LIB to the name of the Python library. 20 | # 21 | # This macro calls AC_SUBST on PYTHON_BIN (via AC_CHECK_PROG), 22 | # PYTHON_INCLUDE_DIR and PYTHON_LIB. 23 | # 24 | # LICENSE 25 | # 26 | # Copyright (c) 2008 Michael Tindal 27 | # 28 | # This program is free software; you can redistribute it and/or modify it 29 | # under the terms of the GNU General Public License as published by the 30 | # Free Software Foundation; either version 2 of the License, or (at your 31 | # option) any later version. 32 | # 33 | # This program is distributed in the hope that it will be useful, but 34 | # WITHOUT ANY WARRANTY; without even the implied warranty of 35 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 36 | # Public License for more details. 37 | # 38 | # You should have received a copy of the GNU General Public License along 39 | # with this program. If not, see . 40 | # 41 | # As a special exception, the respective Autoconf Macro's copyright owner 42 | # gives unlimited permission to copy, distribute and modify the configure 43 | # scripts that are the output of Autoconf when processing the Macro. You 44 | # need not follow the terms of the GNU General Public License when using 45 | # or distributing such scripts, even though portions of the text of the 46 | # Macro appear in them. The GNU General Public License (GPL) does govern 47 | # all other use of the material that constitutes the Autoconf Macro. 48 | # 49 | # This special exception to the GPL applies to versions of the Autoconf 50 | # Macro released by the Autoconf Archive. When you make and distribute a 51 | # modified version of the Autoconf Macro, you may extend this special 52 | # exception to the GPL to apply to your modified version as well. 53 | 54 | #serial 14 55 | 56 | AC_DEFUN([AX_PYTHON], 57 | [AC_MSG_CHECKING(for python build information) 58 | AC_MSG_RESULT([]) 59 | for python in python3.5 python3.4 python3.3 python3.2 python3.1 python3 python2.7 python2.6 python2 python; do 60 | AC_CHECK_PROGS(PYTHON_BIN, [$python]) 61 | ax_python_bin=$PYTHON_BIN 62 | if test x$ax_python_bin != x; then 63 | AC_CHECK_LIB($ax_python_bin, main, ax_python_lib=$ax_python_bin, ax_python_lib=no) 64 | if test x$ax_python_lib == xno; then 65 | AC_CHECK_LIB(${ax_python_bin}m, main, ax_python_lib=${ax_python_bin}m, ax_python_lib=no) 66 | fi 67 | if test x$ax_python_lib == xno; then 68 | AC_CHECK_LIB(${ax_python_bin}mu, main, ax_python_lib=${ax_python_bin}mu, ax_python_lib=no) 69 | fi 70 | if test x$ax_python_lib != xno; then 71 | ax_python_header=`$ax_python_bin -c "from distutils.sysconfig import *; print(get_config_var('CONFINCLUDEPY'))"` 72 | if test x$ax_python_header != x; then 73 | break; 74 | fi 75 | fi 76 | fi 77 | unset ac_cv_prog_PYTHON_BIN 78 | unset PYTHON_BIN 79 | done 80 | if test x$ax_python_bin = x; then 81 | ax_python_bin=no 82 | fi 83 | if test x$ax_python_header = x; then 84 | ax_python_header=no 85 | fi 86 | if test x$ax_python_lib = x; then 87 | ax_python_lib=no 88 | fi 89 | 90 | AC_MSG_RESULT([ results of the Python check:]) 91 | AC_MSG_RESULT([ Binary: $ax_python_bin]) 92 | AC_MSG_RESULT([ Library: $ax_python_lib]) 93 | AC_MSG_RESULT([ Include Dir: $ax_python_header]) 94 | 95 | 96 | PYTHON_FOUND=yes 97 | if test x$ax_python_header != xno; then 98 | PYTHON_INCLUDE_DIR=$ax_python_header 99 | AC_SUBST(PYTHON_INCLUDE_DIR) 100 | else 101 | PYTHON_FOUND=no 102 | fi 103 | 104 | if test x$ax_python_lib != xno; then 105 | PYTHON_LIB=$ax_python_lib 106 | AC_SUBST(PYTHON_LIB) 107 | else 108 | PYTHON_FOUND=no 109 | fi 110 | AC_SUBST(PYTHON_FOUND) 111 | 112 | ])dnl 113 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | aclocal 4 | autoheader 5 | automake --gnu --add-missing 6 | autoconf 7 | -------------------------------------------------------------------------------- /compile_osx.sh: -------------------------------------------------------------------------------- 1 | export LDFLAGS="-L/usr/local/lib -L/usr/local/Cellar/readline/6.3.8/lib" 2 | export CFLAGS="-I/usr/local/include -I/usr/local/Cellar/readline/6.3.8/include" 3 | 4 | ./configure --with-openssl=/usr/local/opt/openssl --disable-liblua 5 | make 6 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* disable extf queries */ 4 | #undef DISABLE_EXTF 5 | 6 | /* Use libevent v1 */ 7 | #undef EVENT_V1 8 | 9 | /* Use libevent v2 */ 10 | #undef EVENT_V2 11 | 12 | /* Define to 1 if you have the `alarm' function. */ 13 | #undef HAVE_ALARM 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_ARPA_INET_H 17 | 18 | /* Define to 1 if you have the `endpwent' function. */ 19 | #undef HAVE_ENDPWENT 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_EXECINFO_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_FCNTL_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_INTTYPES_H 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_LAUXLIB_H 32 | 33 | /* Define to 1 if you have the `config' library (-lconfig). */ 34 | #undef HAVE_LIBCONFIG 35 | 36 | /* Define to 1 if you have the `event' library (-levent). */ 37 | #undef HAVE_LIBEVENT 38 | 39 | /* Define to 1 if you have the `gcrypt' library (-lgcrypt). */ 40 | #undef HAVE_LIBGCRYPT 41 | 42 | /* Define to 1 if you have the `jansson' library (-ljansson). */ 43 | #undef HAVE_LIBJANSSON 44 | 45 | /* Define to 1 if you have `z' library (-lz) */ 46 | #undef HAVE_LIBZ 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #undef HAVE_LUACONF_H 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #undef HAVE_LUALIB_H 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #undef HAVE_LUA_H 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #undef HAVE_MACH_MACH_H 59 | 60 | /* Define to 1 if your system has a GNU libc compatible `malloc' function, and 61 | to 0 otherwise. */ 62 | #undef HAVE_MALLOC 63 | 64 | /* Define to 1 if you have the header file. */ 65 | #undef HAVE_MALLOC_H 66 | 67 | /* Define to 1 if you have the `memmove' function. */ 68 | #undef HAVE_MEMMOVE 69 | 70 | /* Define to 1 if you have the header file. */ 71 | #undef HAVE_MEMORY_H 72 | 73 | /* Define to 1 if you have the `memset' function. */ 74 | #undef HAVE_MEMSET 75 | 76 | /* Define to 1 if you have the `mkdir' function. */ 77 | #undef HAVE_MKDIR 78 | 79 | /* Define to 1 if you have the header file. */ 80 | #undef HAVE_NETDB_H 81 | 82 | /* Define to 1 if you have the header file. */ 83 | #undef HAVE_NETINET_IN_H 84 | 85 | /* Define to 1 if your system has a GNU libc compatible `realloc' function, 86 | and to 0 otherwise. */ 87 | #undef HAVE_REALLOC 88 | 89 | /* Define to 1 if you have the `select' function. */ 90 | #undef HAVE_SELECT 91 | 92 | /* Define to 1 if you have the `socket' function. */ 93 | #undef HAVE_SOCKET 94 | 95 | /* Define to 1 if you have the header file. */ 96 | #undef HAVE_STDINT_H 97 | 98 | /* Define to 1 if you have the header file. */ 99 | #undef HAVE_STDLIB_H 100 | 101 | /* Define to 1 if you have the `strdup' function. */ 102 | #undef HAVE_STRDUP 103 | 104 | /* Define to 1 if you have the header file. */ 105 | #undef HAVE_STRINGS_H 106 | 107 | /* Define to 1 if you have the header file. */ 108 | #undef HAVE_STRING_H 109 | 110 | /* Define to 1 if you have the `strndup' function. */ 111 | #undef HAVE_STRNDUP 112 | 113 | /* Define to 1 if you have the header file. */ 114 | #undef HAVE_SYS_FILE_H 115 | 116 | /* Define to 1 if you have the header file. */ 117 | #undef HAVE_SYS_SOCKET_H 118 | 119 | /* Define to 1 if you have the header file. */ 120 | #undef HAVE_SYS_STAT_H 121 | 122 | /* Define to 1 if you have the header file. */ 123 | #undef HAVE_SYS_TYPES_H 124 | 125 | /* Define to 1 if you have the header file. */ 126 | #undef HAVE_TERMIOS_H 127 | 128 | /* Define to 1 if you have the `uname' function. */ 129 | #undef HAVE_UNAME 130 | 131 | /* Define to 1 if you have the header file. */ 132 | #undef HAVE_UNISTD_H 133 | 134 | /* Define to 1 if the system has the `__builtin_bswap32' built-in function */ 135 | #undef HAVE___BUILTIN_BSWAP32 136 | 137 | /* Define to the address where bug reports for this package should be sent. */ 138 | #undef PACKAGE_BUGREPORT 139 | 140 | /* Define to the full name of this package. */ 141 | #undef PACKAGE_NAME 142 | 143 | /* Define to the full name and version of this package. */ 144 | #undef PACKAGE_STRING 145 | 146 | /* Define to the one symbol short name of this package. */ 147 | #undef PACKAGE_TARNAME 148 | 149 | /* Define to the home page for this package. */ 150 | #undef PACKAGE_URL 151 | 152 | /* Define to the version of this package. */ 153 | #undef PACKAGE_VERSION 154 | 155 | /* Use custom prog name */ 156 | #undef PROG_NAME 157 | 158 | /* Define to 1 if you have the ANSI C header files. */ 159 | #undef STDC_HEADERS 160 | 161 | /* avoid OpenSSL entirely, use libgcrypt instead (this can't read *.pub files, 162 | though.) */ 163 | #undef TGL_AVOID_OPENSSL 164 | 165 | /* use json */ 166 | #undef USE_JSON 167 | 168 | /* use lua */ 169 | #undef USE_LUA 170 | 171 | /* use python */ 172 | #undef USE_PYTHON 173 | 174 | /* fixed for correct valgrind work */ 175 | #undef VALGRIND_FIXES 176 | 177 | /* Define to `int' if doesn't define. */ 178 | #undef gid_t 179 | 180 | /* Define to `__inline__' or `__inline' if that's what the C compiler 181 | calls it, or to nothing if 'inline' is not supported under any name. */ 182 | #ifndef __cplusplus 183 | #undef inline 184 | #endif 185 | 186 | /* Define to rpl_malloc if the replacement function should be used. */ 187 | #undef malloc 188 | 189 | /* Define to rpl_realloc if the replacement function should be used. */ 190 | #undef realloc 191 | 192 | /* Define to `unsigned int' if does not define. */ 193 | #undef size_t 194 | 195 | /* Define to `int' if doesn't define. */ 196 | #undef uid_t 197 | -------------------------------------------------------------------------------- /config.sample: -------------------------------------------------------------------------------- 1 | # This is an empty config file 2 | # Feel free to put something here 3 | 4 | default_profile = "production"; 5 | 6 | production = { 7 | config_directory = ".telegram/production"; 8 | test = false; 9 | msg_num = true; 10 | }; 11 | 12 | test_dc1 = { 13 | config_directory = ".telegram/test_dc1"; 14 | test = true; 15 | msg_num = true; 16 | }; 17 | 18 | binlog = { 19 | config_directory = ".telegram/binlog"; 20 | test = false; 21 | msg_num = true; 22 | log_level = 2; 23 | }; 24 | 25 | binlog_mts = { 26 | config_directory = ".telegram/binlog_mts"; 27 | test = false; 28 | msg_num = true; 29 | log_level = 2; 30 | }; 31 | 32 | mega = { 33 | config_directory = ".telegram/mega"; 34 | test = false; 35 | msg_num = true; 36 | log_level = 2; 37 | }; 38 | 39 | new = { 40 | config_directory = ".telegram/new"; 41 | test = false; 42 | msg_num = true; 43 | }; 44 | 45 | test = { 46 | config_directory = ".telegram/test"; 47 | test = true; 48 | msg_num = true; 49 | }; 50 | 51 | test1 = { 52 | config_directory = ".telegram/test1"; 53 | msg_num = true; 54 | }; 55 | 56 | test2 = { 57 | config_directory = ".telegram/test2"; 58 | msg_num = true; 59 | pfs_enabled = true; 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ([2.68]) 2 | AC_INIT([telegram-cli], [1.0]) 3 | AC_CONFIG_SRCDIR([config.h.in]) 4 | AC_CONFIG_HEADERS([config.h]) 5 | 6 | m4_include([ax_lua.m4]) 7 | m4_include([ax_python.m4]) 8 | m4_include([m4_ax_check_openssl.m4]) 9 | m4_include([m4_ax_check_zlib.m4]) 10 | m4_include([m4-ax_gcc_builtin.m4]) 11 | 12 | # Checks for programs. 13 | AC_PROG_CC 14 | 15 | # BSD locations for headers and libraries from packages, Linux locations for self-compiled stuff. 16 | CPPFLAGS="$CPPFLAGS -I/usr/local/include" 17 | LDFLAGS="$LDFLAGS -L/usr/local/lib" 18 | 19 | # Checks for libraries. 20 | AC_SEARCH_LIBS([clock_gettime], [rt]) 21 | AC_SEARCH_LIBS([backtrace], [execinfo]) 22 | AC_CHECK_LIB([event], [event_base_new], [], [AC_MSG_ERROR([no libevent found])]) 23 | 24 | EVENT_VER="" 25 | 26 | AC_CHECK_HEADER(event2/event.h, [AC_DEFINE([EVENT_V2], [1], [Use libevent v2])], [ 27 | AC_CHECK_HEADER(event.h, [AC_DEFINE([EVENT_V1], [1], [Use libevent v1])], [AC_MSG_ERROR([no libevent found])]) 28 | ]) 29 | 30 | EXTRA_LIBS="" 31 | 32 | # OPENSSL_INCLUDES to the include directives required 33 | # OPENSSL_LIBS to the -l directives required 34 | # OPENSSL_LDFLAGS to the -L or -R flags required 35 | 36 | AC_ARG_ENABLE(openssl,[ --disable-openssl disables OpenSSL, and don't link against it 37 | (this can't read *.pub files, though.)], 38 | [ 39 | if test "x$enableval" = "xno" ; then 40 | AC_DEFINE([TGL_AVOID_OPENSSL],[1],[avoid OpenSSL entirely, use libgcrypt instead (this can't read *.pub files, though.)]) 41 | AC_CHECK_LIB([gcrypt], [gcry_mpi_snatch], [], [AC_MSG_ERROR(["Need libgcrypt >= 1.60"])]) 42 | else 43 | # Don't be annoying, so don't inform the user about --disable-openssl 44 | AX_CHECK_OPENSSL(,[AC_MSG_ERROR([No openssl found.])]) 45 | fi 46 | ],[ 47 | AX_CHECK_OPENSSL(,[AC_MSG_ERROR([No openssl found. With --disable-openssl, libtgl will use libgcrypt instead.])]) 48 | ]) 49 | AX_CHECK_ZLIB(, [AC_MSG_ERROR([No zlib found])]) 50 | 51 | AC_CHECK_LIB([readline], [rl_save_prompt], [ EXTRA_LIBS="${EXTRA_LIBS} -lreadline" ; ], [AC_MSG_ERROR([no libreadline found])]) 52 | 53 | AC_MSG_CHECKING([for libconfig]) 54 | AC_ARG_ENABLE(libconfig,[--enable-libconfig/--disable-libconfig], 55 | [ 56 | if test "x$enableval" = "xno" ; then 57 | AC_MSG_RESULT([disabled]) 58 | else 59 | AC_MSG_RESULT([enabled]) 60 | AC_CHECK_LIB([config],[config_init],[],AC_MSG_ERROR([No libconfig found. Try --disable-libconfig])) 61 | fi 62 | ],[ 63 | AC_MSG_RESULT([enabled]) 64 | AC_CHECK_LIB([config],[config_init],[],AC_MSG_ERROR([No libconfig found. Try --disable-libconfig])) 65 | ]) 66 | 67 | AC_ARG_ENABLE(extf,[--enable-extf/--disable-extf], 68 | [ 69 | if test "x$enableval" = "xno" ; then 70 | AC_DEFINE([DISABLE_EXTF],[1],[disable extf queries]) 71 | fi 72 | ],[ 73 | ]) 74 | 75 | AC_MSG_CHECKING([for liblua]) 76 | AC_ARG_ENABLE(liblua,[--enable-liblua/--disable-liblua], 77 | [ 78 | if test "x$enableval" = "xno" ; then 79 | AC_MSG_RESULT([disabled]) 80 | else 81 | AC_MSG_RESULT([enabled]) 82 | AX_PROG_LUA([],[], 83 | [ 84 | AX_LUA_HEADERS([],[AC_MSG_ERROR([No lua headers found. Try --disable-liblua])]) 85 | AX_LUA_LIBS([],[AC_MSG_ERROR([No lua libs found. Try --disable-liblua])]) 86 | [EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; ] 87 | [CPPFLAGS="${CPPFLAGS} ${LUA_INCLUDE}" ; ] 88 | AC_DEFINE(USE_LUA,1,[use lua]) 89 | ], 90 | [ 91 | AC_MSG_ERROR([No lua found. Try --disable-liblua]) 92 | ]) 93 | fi 94 | ],[ 95 | AC_MSG_RESULT([enabled]) 96 | AX_PROG_LUA([],[], 97 | [ 98 | AX_LUA_HEADERS([],[AC_MSG_ERROR([No lua headers found. Try --disable-liblua])]) 99 | AX_LUA_LIBS([],[AC_MSG_ERROR([No lua libs found. Try --disable-liblua])]) 100 | [EXTRA_LIBS="${EXTRA_LIBS} ${LUA_LIB}" ; ] 101 | [CPPFLAGS="${CPPFLAGS} ${LUA_INCLUDE}" ; ] 102 | AC_DEFINE(USE_LUA,1,[use lua]) 103 | ], 104 | [ 105 | AC_MSG_ERROR([No lua found. Try --disable-liblua]) 106 | ]) 107 | ]) 108 | 109 | AC_MSG_CHECKING([for python]) 110 | AC_ARG_ENABLE(python,[--enable-python/--disable-python], 111 | [ 112 | if test "x$enableval" = "xyes" ; then 113 | AC_MSG_RESULT([disabled]) 114 | else 115 | AC_MSG_RESULT([enabled]) 116 | 117 | AX_PYTHON() 118 | AC_SUBST([PYTHON_FOUND]) 119 | if test $PYTHON_FOUND = no ; then 120 | AC_MSG_ERROR([No supported python lib version found. Try --disable-python]) 121 | else 122 | AC_SUBST([PYTHON_LIBS]) 123 | AC_SUBST([PYTHON_CFLAGS]) 124 | EXTRA_LIBS="${EXTRA_LIBS} -l${PYTHON_LIB}" 125 | CPPFLAGS="${CPPFLAGS} -I${PYTHON_INCLUDE_DIR}" 126 | AC_DEFINE(USE_PYTHON,1,[use python]) 127 | fi 128 | fi 129 | ],[ 130 | AC_MSG_RESULT([disabled]) 131 | ]) 132 | 133 | 134 | 135 | AC_MSG_CHECKING([for libjansson]) 136 | AC_ARG_ENABLE(json,[--enable-json/--disable-json], 137 | [ 138 | if test "x$enableval" = "xno" ; then 139 | AC_MSG_RESULT([disabled]) 140 | else 141 | AC_MSG_RESULT([enabled]) 142 | AC_CHECK_LIB([jansson],[json_array_set_new],[],AC_MSG_ERROR([No libjansson found. Try --disable-json])) 143 | AC_DEFINE(USE_JSON,1,[use json]) 144 | fi 145 | ],[ 146 | AC_MSG_RESULT([enabled]) 147 | AC_CHECK_LIB([jansson],[json_array_set_new],[],AC_MSG_ERROR([No libjansson found. Try --disable-json])) 148 | AC_DEFINE(USE_JSON,1,[use json]) 149 | ]) 150 | 151 | #check for custom prog name 152 | AC_MSG_CHECKING([progname]) 153 | AC_ARG_WITH(progname,[--with-progname=], 154 | [ 155 | if test "x$with_progname" = "xno" ; then 156 | AC_MSG_RESULT([default]) 157 | elif test "x$with_progname" = "xyes" ; then 158 | AC_MSG_RESULT([default]) 159 | else 160 | AC_MSG_RESULT(["$with_progname"]) 161 | AC_DEFINE_UNQUOTED([PROG_NAME], ["$with_progname"], [Use custom prog name]) 162 | fi 163 | ],[ 164 | AC_MSG_RESULT([default]) 165 | ]) 166 | 167 | AC_ARG_ENABLE(valgrind,[--enable-valgrind/--disable-valgrind], 168 | [ 169 | if test "x$enableval" = "xyes" ; then 170 | AC_CHECK_HEADER(valgrind/memcheck.h, [AC_DEFINE([VALGRIND_FIXES], [1], [fixed for correct valgrind work])], [ 171 | ]) 172 | fi 173 | ],[ 174 | ]) 175 | 176 | 177 | # Checks for header files. 178 | AC_CHECK_HEADERS([execinfo.h fcntl.h malloc.h netdb.h stdlib.h string.h unistd.h arpa/inet.h mach/mach.h netinet/in.h sys/file.h sys/socket.h termios.h]) 179 | 180 | # Checks for typedefs, structures, and compiler characteristics. 181 | AC_TYPE_SIZE_T 182 | AC_TYPE_UID_T 183 | AC_C_INLINE 184 | 185 | # Checks for library functions. 186 | AC_FUNC_MALLOC 187 | AC_FUNC_REALLOC 188 | AC_CHECK_FUNCS([alarm endpwent memset memmove mkdir select socket strdup strndup uname]) 189 | 190 | AX_GCC_BUILTIN(__builtin_bswap32) 191 | 192 | AC_SUBST(EXTRA_LIBS) 193 | AC_CONFIG_FILES([Makefile]) 194 | AC_OUTPUT 195 | 196 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | telegram-cli (1.0.6-1) unstable; urgency=low 2 | 3 | telegram-cli (0.1-2) unstable; urgency=low 4 | 5 | * Updated Standards-Version to 3.9.5 6 | * Sorted Build/Depends fields. 7 | 8 | -- Kartik Mistry Fri, 21 Feb 2014 17:02:38 +0530 9 | 10 | telegram-cli (0.1-1) unstable; urgency=low 11 | 12 | * Upstream update version 13 | * Inpliment -e option 14 | 15 | -- Steve Illichevsky Sat, 11 Oct 2014 08:47:07 +0400 16 | 17 | telegram-cli (1.0.5.1-1) unstable; urgency=low 18 | 19 | * Initial release 20 | 21 | -- Steve Illichevsky Sun, 05 Oct 2014 09:37:06 +0400 22 | -------------------------------------------------------------------------------- /debian/clean: -------------------------------------------------------------------------------- 1 | Makefile -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: telegram-cli 2 | Section: net 3 | Priority: optional 4 | Maintainer: Cleto Martín 5 | Build-Depends: autoconf-archive, 6 | autotools-dev, 7 | debhelper (>= 8.0.0), 8 | libconfig-dev, 9 | libreadline-dev, 10 | libssl-dev, 11 | libevent-dev, 12 | libjansson-dev, 13 | libpython-dev, 14 | liblua5.2-dev, 15 | libgcrypt-dev, 16 | lua-lgi, 17 | lua5.2 18 | Standards-Version: 3.9.5 19 | Homepage: https://github.com/vysheng/tg 20 | Vcs-Git: git://github.com/vysheng/tg.git 21 | Vcs-Browser: https://github.com/vysheng/tg 22 | 23 | Package: telegram-cli 24 | Architecture: any 25 | Depends: ${misc:Depends}, ${shlibs:Depends} 26 | Description: Command-line interface for Telegram messenger 27 | Telegram messenger is a cloud-based instant messaging designed for 28 | smart phones and similar to Whatsapp but more flexible, and 29 | powerful. You can send messages, photos, videos and documents to 30 | people who are in your phone contacts (and have Telegram). Telegram 31 | also supports secret chats whose provide a private (encrypted) way of 32 | communication. 33 | . 34 | This package contains a command-line based client for Telegram with 35 | the following features: 36 | * Colored terminal messages. 37 | * Message management: history, stats, etc. 38 | * Group chat: create and manage groups. 39 | * Secret chat: secured and encrypted conversations. 40 | * Contact management: add/edit/remove contacts. 41 | * Multimedia support: send/load photos and videos. 42 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://dep.debian.net/deps/dep5 2 | Upstream-Name: telegram-cli 3 | Source: https://github.com/vysheng/tg 4 | 5 | Files: * 6 | Copyright: 2013-2014 Vitaly Valtman 7 | License: GPL-3.0+ 8 | 9 | Files: debian/* 10 | Copyright: 2014 Steve Illichevsky 11 | License: GPL-3.0+ 12 | 13 | License: GPL-3.0+ 14 | This program is free software: you can redistribute it and/or modify 15 | it under the terms of the GNU General Public License as published by 16 | the Free Software Foundation, either version 3 of the License, or 17 | (at your option) any later version. 18 | . 19 | This package is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | . 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see . 26 | . 27 | On Debian systems, the complete text of the GNU General 28 | Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". 29 | 30 | # Please also look if there are files or directories which have a 31 | # different copyright/license attached and list them here. 32 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README.es 2 | README-LUA 3 | README.md 4 | #telegram-cli.8 5 | -------------------------------------------------------------------------------- /debian/install: -------------------------------------------------------------------------------- 1 | #bin/telegram-cli usr/bin 2 | server.pub etc/telegram-cli 3 | 4 | #bin/telegram-cli usr/share/telegram-daemon/bin 5 | #start-telegram-daemon /usr/share/telegram-daemon/bin 6 | test.lua var/lib/telegram-cli/ 7 | #telegram-daemon etc/init.d 8 | server.pub etc/telegram 9 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | export DH_VERBOSE=1 11 | 12 | VERSION=$(shell dpkg-parsechangelog | sed -n 's/^Version: //p' | cut -f1 -d'-') 13 | PACKAGE_NAME=$(shell dpkg-parsechangelog | sed -n 's/^Source: //p') 14 | 15 | override_dh_auto_configure: 16 | ./configure --disable-openssl --prefix=/usr 17 | 18 | override_dh_usrlocal: 19 | 20 | 21 | %: 22 | cp tg-server.pub server.pub 23 | dh $@ --with autotools-dev 24 | rm server.pub 25 | 26 | build-orig: 27 | mkdir -p $(PACKAGE_NAME)-$(VERSION) 28 | tar --exclude=ax_lua.m4 --exclude=debian --exclude=\.pc \ 29 | --exclude=$(PACKAGE_NAME)-$(VERSION) -cf - . \ 30 | | ( cd $(PACKAGE_NAME)-$(VERSION) && tar xf - ) 31 | tar -cf ../$(PACKAGE_NAME)_$(VERSION).orig.tar $(PACKAGE_NAME)-$(VERSION) 32 | $(RM) -r $(PACKAGE_NAME)-$(VERSION) 33 | xz ../$(PACKAGE_NAME)_$(VERSION).orig.tar 34 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/telegram-cli.8: -------------------------------------------------------------------------------- 1 | .TH man 8 "02 October 2014" "1.0.5.1" "telegram-cli man page" 2 | .SH NAME 3 | telegram-cli \- Command-line interface for Telegram messenger 4 | .SH SYNOPSIS 5 | telegram-cli -k [keyfile] 6 | .SH DESCRIPTION 7 | Telegram messenger is a cloud-based instant messaging designed for 8 | smart phones and similar to Whatsapp but more flexible, and 9 | powerful. You can send messages, photos, videos and documents to 10 | people who are in your phone contacts (and have Telegram). Telegram 11 | also supports secret chats whose provide a private (encrypted) way of 12 | communication. 13 | . 14 | This package contains a command-line based client for Telegram with 15 | the following features: 16 | * Colored terminal messages. 17 | * Message management: history, stats, etc. 18 | * Group chat: create and manage groups. 19 | * Secret chat: secured and encrypted conversations. 20 | * Contact management: add/edit/remove contacts. 21 | * Multimedia support: send/load photos and videos. 22 | .SH OPTIONS 23 | Telegram-cli Usage 24 | -u specify username (would not be asked during authorization) 25 | -k specify location of public key (possible multiple entries) 26 | -v increase verbosity (0-ERROR 1-WARNIN 2-NOTICE 3+-DEBUG-levels) 27 | -N message num mode 28 | -c config file name 29 | -p use specified profile 30 | -l log level 31 | -f during authorization fetch all messages since registration 32 | -E disable auto accept of encrypted chats 33 | -s lua script file 34 | -W send dialog_list query and wait for answer before reading input 35 | -C disable color output 36 | -R disable readline 37 | -d daemon mode 38 | -L log file name 39 | -U change uid after start 40 | -G change gid after start 41 | -D disable output 42 | -P port to listen for input commands 43 | -S unix socket to create 44 | .SH SEE ALSO 45 | .SH BUGS 46 | No known bugs. 47 | .SH AUTHOR 48 | Vitaliy Vatman (-@-) 49 | -------------------------------------------------------------------------------- /debian/telegram-cli.logrotate: -------------------------------------------------------------------------------- 1 | /var/lib/telegram-cli/*.log { 2 | daily 3 | missingok 4 | rotate 31 5 | compress 6 | notifempty 7 | nocreate 8 | } 9 | -------------------------------------------------------------------------------- /debian/telegram-cli.manpages: -------------------------------------------------------------------------------- 1 | debian/telegram-cli.8 2 | -------------------------------------------------------------------------------- /debian/telegram-cli.postinst.debhelper: -------------------------------------------------------------------------------- 1 | # Automatically added by dh_installinit 2 | if [ -e "/etc/init/telegram-cli.conf" ]; then 3 | invoke-rc.d telegram-cli start || exit $? 4 | fi 5 | # End automatically added section 6 | # Automatically added by dh_installinit 7 | update-rc.d -f telegram-cli remove >/dev/null || exit $? 8 | # End automatically added section 9 | -------------------------------------------------------------------------------- /debian/telegram-cli.preinst: -------------------------------------------------------------------------------- 1 | adduser --system --home /var/lib/telegram-cli --gecos "Telegram Daemon User" --group telegramd -------------------------------------------------------------------------------- /debian/telegram-cli.preinst.debhelper: -------------------------------------------------------------------------------- 1 | # Automatically added by dh_installinit 2 | if [ "$1" = install ] || [ "$1" = upgrade ]; then 3 | if [ -e "/etc/init.d/telegram-cli" ] && [ ! -L "/etc/init.d/telegram-cli" ]; then 4 | if [ "`md5sum \"/etc/init.d/telegram-cli\" | sed -e \"s/ .*//\"`" != \ 5 | "`dpkg-query -W -f='${Conffiles}' telegram-cli | sed -n -e \"\\\\' /etc/init.d/telegram-cli '{s/ obsolete$//;s/.* //p}\"`" ] 6 | then 7 | echo "Obsolete conffile /etc/init.d/telegram-cli has been modified by you, renaming to .dpkg-bak" 8 | mv -f "/etc/init.d/telegram-cli" "/etc/init.d/telegram-cli.dpkg-bak" 9 | else 10 | rm -f "/etc/init.d/telegram-cli" 11 | fi 12 | fi 13 | fi 14 | # End automatically added section 15 | -------------------------------------------------------------------------------- /debian/telegram-cli.prerm: -------------------------------------------------------------------------------- 1 | # Automatically added by dh_installinit 2 | if [ -e "/etc/init/telegram-cli.conf" ]; then 3 | invoke-rc.d telegram-cli stop || exit $? 4 | fi 5 | # End automatically added section 6 | 7 | deluser --remove-home telegramd -------------------------------------------------------------------------------- /debian/telegram-cli.prerm.debhelper: -------------------------------------------------------------------------------- 1 | # Automatically added by dh_installinit 2 | if [ -e "/etc/init/telegram-cli.conf" ]; then 3 | invoke-rc.d telegram-cli stop || exit $? 4 | fi 5 | # End automatically added section 6 | -------------------------------------------------------------------------------- /debian/telegram-cli.upstart: -------------------------------------------------------------------------------- 1 | # Service 2 | 3 | setuid telegramd 4 | setgid telegramd 5 | 6 | script 7 | exec /usr/bin/telegram-cli -s /var/lib/telegram-cli/test.lua -W -d -C -vvvv -l 0 -L /var/lib/telegram-cli/telegram-cli.log -P 8002 8 | # This example for Daemon which keep log in his home directory 9 | # This daemon can listen localhost:8002 tcp port 10 | end script 11 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | 3 | opts=filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/tg-$1\.tar\.gz/ \ 4 | https://github.com/kenorb-contrib/tg/tags .*/v?(\d\S*)\.tar\.gz 5 | -------------------------------------------------------------------------------- /event-old.h: -------------------------------------------------------------------------------- 1 | #ifndef __EVENT_OLD_H__ 2 | #define __EVENT_OLD_H__ 3 | 4 | #include 5 | #include 6 | 7 | #define BEV_EVENT_READ EVBUFFER_READ 8 | #define BEV_EVENT_WRITE EVBUFFER_WRITE 9 | #define BEV_EVENT_EOF EVBUFFER_EOF 10 | #define BEV_EVENT_ERROR EVBUFFER_ERROR 11 | #define BEV_EVENT_TIMEOUT EVBUFFER_TIMEOUT 12 | 13 | typedef int evutil_socket_t; 14 | 15 | static inline struct event *event_new (struct event_base *base, int fd, int what, void(*callback)(int, short, void *), void *arg) __attribute__ ((unused)); 16 | static inline struct event *event_new (struct event_base *base, int fd, int what, void(*callback)(int, short, void *), void *arg) { 17 | struct event *ev = malloc (sizeof (*ev)); 18 | event_set (ev, fd, what, callback, arg); 19 | event_base_set (base, ev); 20 | return ev; 21 | } 22 | 23 | static inline struct event *evtimer_new (struct event_base *base, void(*callback)(int, short, void *), void *arg) __attribute__ ((unused)); 24 | static inline struct event *evtimer_new (struct event_base *base, void(*callback)(int, short, void *), void *arg) { 25 | struct event *ev = malloc (sizeof (*ev)); 26 | event_set (ev, -1, 0, callback, arg); 27 | event_base_set (base, ev); 28 | return ev; 29 | } 30 | 31 | static void event_free (struct event *ev) __attribute__ ((unused)); 32 | static void event_free (struct event *ev) { 33 | event_del (ev); 34 | free (ev); 35 | } 36 | 37 | static struct bufferevent *bufferevent_socket_new (struct event_base *base, int fd, int flags) __attribute__ ((unused)); 38 | static struct bufferevent *bufferevent_socket_new (struct event_base *base, int fd, int flags) { 39 | assert (!flags); 40 | struct bufferevent *bev = bufferevent_new(fd, 0, 0, 0, 0); 41 | bufferevent_base_set (base, bev); 42 | return bev; 43 | } 44 | 45 | static inline void *event_get_callback_arg(const struct event *ev) { 46 | return ev->ev_arg; 47 | } 48 | #endif 49 | -------------------------------------------------------------------------------- /gentoo/net-im/telegram-cli/Manifest: -------------------------------------------------------------------------------- 1 | EBUILD telegram-cli-9999.ebuild 926 SHA256 d9c959af30c77afe8e6b1cee162e5362edfb9da6980b53ef71c3cae5f621bf05 SHA512 eeef9e1d2d7cd0b600be0d44de39e9c38207d5fb8f675e7ba239c1e907ab5df6e198a5810e6bb08445c7c2a98cc50bf78554f52b4c7c0534f111bfa3256b8186 WHIRLPOOL 700a6fd9930074ec36dfb3f4b248a43e6d7c0ab0f97ed6b56343e79fb15a087d99eb52ad67a818e67cbb1a848d65cc395f60b319f3fda60c87c10e9f4e132838 2 | -------------------------------------------------------------------------------- /gentoo/net-im/telegram-cli/telegram-cli-9999.ebuild: -------------------------------------------------------------------------------- 1 | EAPI=6 2 | 3 | inherit git-r3 4 | 5 | HOMEPAGE="https://github.com/vysheng/tg" 6 | DESCRIPTION="Command line interface client for Telegram" 7 | EGIT_REPO_URI="https://github.com/vysheng/tg.git" 8 | if [[ "${PV}" -ne "9999" ]]; then 9 | EGIT_COMMIT="refs/tags/${PV}" 10 | KEYWORDS="~amd64 ~x86" 11 | else 12 | KEYWORDS="" 13 | fi 14 | LICENSE="GPL-2" 15 | SLOT="0" 16 | IUSE="lua json" 17 | 18 | DEPEND=" 19 | sys-libs/zlib 20 | sys-libs/readline 21 | dev-libs/libconfig 22 | dev-libs/openssl 23 | dev-libs/libevent 24 | lua? ( dev-lang/lua ) 25 | json? ( dev-libs/jansson ) 26 | " 27 | RDEPEND="${DEPEND}" 28 | 29 | src_configure() { 30 | econf $(use_enable lua liblua) \ 31 | $(use_enable json) 32 | } 33 | 34 | src_install() { 35 | dobin bin/telegram-cli 36 | 37 | insinto /etc/telegram-cli/ 38 | newins tg-server.pub server.pub 39 | } 40 | -------------------------------------------------------------------------------- /interface.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of telegram-cli. 3 | 4 | Telegram-cli is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | Telegram-cli is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this telegram-cli. If not, see . 16 | 17 | Copyright Vitaly Valtman 2013-2015 18 | */ 19 | #ifndef __INTERFACE_H__ 20 | #define __INTERFACE_H__ 21 | #include 22 | #include 23 | 24 | #define COLOR_RED "\001\033[0;31m\002" 25 | #define COLOR_REDB "\001\033[1;31m\002" 26 | #define COLOR_NORMAL "\001\033[0m\002" 27 | #define COLOR_GREEN "\001\033[32;1m\002" 28 | #define COLOR_GREY "\001\033[37;1m\002" 29 | #define COLOR_YELLOW "\001\033[33;1m\002" 30 | #define COLOR_BLUE "\001\033[34;1m\002" 31 | #define COLOR_MAGENTA "\001\033[35;1m\002" 32 | #define COLOR_CYAN "\001\033[36;1m\002" 33 | #define COLOR_LCYAN "\001\033[0;36m\002" 34 | 35 | #define COLOR_INVERSE "\001\033[7m\002" 36 | 37 | char *get_default_prompt (void); 38 | char *complete_none (const char *text, int state); 39 | char **complete_text (char *text, int start, int end); 40 | void interpreter (char *line); 41 | void interpreter_ex (char *line, void *ex); 42 | 43 | void rprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2))); 44 | void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2))); 45 | 46 | #define vlogprintf(v,...) \ 47 | do { \ 48 | if (TLS->verbosity >= (v)) {\ 49 | logprintf (__VA_ARGS__);\ 50 | }\ 51 | } while (0);\ 52 | 53 | 54 | //void hexdump (int *in_ptr, int *in_end); 55 | 56 | struct bufferevent; 57 | struct in_ev { 58 | struct bufferevent *bev; 59 | char in_buf[4096]; 60 | int in_buf_pos; 61 | int refcnt; 62 | int error; 63 | int fd; 64 | }; 65 | 66 | 67 | struct tgl_message; 68 | struct in_ev; 69 | void print_message (struct in_ev *ev, struct tgl_message *M); 70 | void print_chat_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C); 71 | void print_channel_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C); 72 | void print_user_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *U); 73 | void print_encr_chat_name_full (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C); 74 | void print_encr_chat_name (struct in_ev *ev, tgl_peer_id_t id, tgl_peer_t *C); 75 | //void print_media (struct tgl_message_media *M); 76 | // 77 | void pop_color (void); 78 | void push_color (const char *color); 79 | void print_start (void); 80 | void print_end (void); 81 | void print_date_full (struct in_ev *ev, long t); 82 | void print_date (struct in_ev *ev, long t); 83 | 84 | void play_sound (void); 85 | void update_prompt (void); 86 | void set_interface_callbacks (void); 87 | 88 | char *print_permanent_msg_id (tgl_message_id_t id); 89 | char *print_permanent_peer_id (tgl_peer_id_t id); 90 | tgl_peer_id_t parse_input_peer_id (const char *s, int l, int mask); 91 | tgl_message_id_t parse_input_msg_id (const char *s, int l); 92 | #endif 93 | -------------------------------------------------------------------------------- /json-tg.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #ifdef USE_JSON 3 | 4 | #include 5 | #include "json-tg.h" 6 | #include 7 | #include 8 | #include "interface.h" 9 | #include 10 | //format time: 11 | #include 12 | 13 | #ifndef json_boolean 14 | #define json_boolean(val) ((val) ? json_true() : json_false()) 15 | #endif 16 | 17 | extern struct tgl_state *TLS; 18 | 19 | void json_pack_peer_type (json_t *res, tgl_peer_id_t id) { 20 | int x = tgl_get_peer_type (id); 21 | switch (x) { 22 | case TGL_PEER_USER: 23 | assert (json_object_set_new (res, "peer_type", json_string ("user")) >= 0); 24 | break; 25 | case TGL_PEER_CHAT: 26 | assert (json_object_set_new (res, "peer_type", json_string ("chat")) >= 0); 27 | break; 28 | case TGL_PEER_ENCR_CHAT: 29 | assert (json_object_set_new (res, "peer_type", json_string ("encr_chat")) >= 0); 30 | break; 31 | case TGL_PEER_CHANNEL: 32 | assert (json_object_set_new (res, "peer_type", json_string ("channel")) >= 0); 33 | break; 34 | default: 35 | assert (0); 36 | } 37 | } 38 | 39 | int str_format_time(long when, char* string) 40 | { 41 | struct tm *tm = localtime ((void *)&when); 42 | return sprintf (string, "%04d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); 43 | } 44 | 45 | void json_pack_user (json_t *res, tgl_peer_t *P) { 46 | if (P->user.first_name) { 47 | assert (json_object_set_new (res, "first_name", json_string (P->user.first_name)) >= 0); 48 | } 49 | 50 | if (P->user.status.when) { 51 | static char s[20]; 52 | str_format_time(P->user.status.when, s); 53 | assert (json_object_set_new (res, "when", json_string (s)) >= 0); 54 | } 55 | 56 | if (P->user.last_name) { 57 | assert (json_object_set_new (res, "last_name", json_string (P->user.last_name)) >= 0); 58 | } 59 | if (P->user.real_first_name) { 60 | assert (json_object_set_new (res, "real_first_name", json_string (P->user.real_first_name)) >= 0); 61 | } 62 | if (P->user.real_last_name) { 63 | assert (json_object_set_new (res, "real_last_name", json_string (P->user.real_last_name)) >= 0); 64 | } 65 | if (P->user.phone) { 66 | assert (json_object_set_new (res, "phone", json_string (P->user.phone)) >= 0); 67 | } 68 | if (P->user.username) { 69 | assert (json_object_set_new (res, "username", json_string (P->user.username)) >= 0); 70 | } 71 | } 72 | 73 | void json_pack_chat (json_t *res, tgl_peer_t *P) { 74 | assert (P->chat.title); 75 | assert (json_object_set_new (res, "title", json_string (P->chat.title)) >= 0); 76 | tgl_peer_id_t admin_id = TGL_MK_USER (P->chat.admin_id); 77 | assert (json_object_set_new (res, "admin", json_pack_peer (admin_id)) >= 0); 78 | assert (json_object_set_new (res, "members_num", json_integer (P->chat.users_num)) >= 0); 79 | if (P->chat.user_list) { 80 | json_t *m = json_array (); 81 | assert (m); 82 | 83 | int i; 84 | for (i = 0; i < P->chat.users_num; i++) { 85 | tgl_peer_id_t user_id = TGL_MK_USER (P->chat.user_list[i].user_id); 86 | tgl_peer_id_t inviter_id = TGL_MK_USER (P->chat.user_list[i].inviter_id); 87 | json_t *peer = json_pack_peer (user_id); 88 | assert (json_object_set_new (peer, "inviter", json_pack_peer (inviter_id)) >= 0); 89 | assert (json_array_append_new (m, peer) >= 0); 90 | } 91 | 92 | assert (json_object_set_new (res, "members", m) >= 0); 93 | } 94 | } 95 | 96 | void json_pack_channel (json_t *res, tgl_peer_t *P) { 97 | assert (P->channel.title); 98 | assert (json_object_set_new (res, "title", json_string (P->channel.title)) >= 0); 99 | assert (json_object_set_new (res, "participants_count", json_integer (P->channel.participants_count)) >= 0); 100 | assert (json_object_set_new (res, "admins_count", json_integer (P->channel.admins_count)) >= 0); 101 | assert (json_object_set_new (res, "kicked_count", json_integer (P->channel.kicked_count)) >= 0); 102 | } 103 | 104 | 105 | void json_pack_encr_chat (json_t *res, tgl_peer_t *P) { 106 | assert (json_object_set_new (res, "user", json_pack_peer (TGL_MK_USER (P->encr_chat.user_id))) >= 0); 107 | } 108 | 109 | json_t *json_pack_peer (tgl_peer_id_t id) { 110 | tgl_peer_t *P = tgl_peer_get (TLS, id); 111 | //assert (P); 112 | json_t *res = json_object (); 113 | assert (json_object_set_new (res, "id", json_string (print_permanent_peer_id (id))) >= 0); 114 | 115 | json_pack_peer_type (res, id); 116 | assert (json_object_set_new (res, "peer_id", json_integer (tgl_get_peer_id (id))) >= 0); 117 | 118 | assert (res); 119 | 120 | if (!P || !(P->flags & TGLPF_CREATED)) { 121 | static char s[100]; 122 | switch (tgl_get_peer_type (id)) { 123 | case TGL_PEER_USER: 124 | sprintf (s, "user#%d", tgl_get_peer_id (id)); 125 | break; 126 | case TGL_PEER_CHAT: 127 | sprintf (s, "chat#%d", tgl_get_peer_id (id)); 128 | break; 129 | case TGL_PEER_CHANNEL: 130 | sprintf (s, "channel#%d", tgl_get_peer_id (id)); 131 | break; 132 | case TGL_PEER_ENCR_CHAT: 133 | sprintf (s, "encr_chat#%d", tgl_get_peer_id (id)); 134 | break; 135 | default: 136 | assert (0); 137 | } 138 | 139 | assert (json_object_set_new (res, "print_name", json_string (s)) >= 0); 140 | return res; 141 | } 142 | if(P->print_name != NULL){ 143 | assert (json_object_set_new (res, "print_name", json_string (P->print_name)) >= 0); 144 | } else { 145 | assert (json_object_set_new (res, "print_name", json_string ("")) >= 0); 146 | } 147 | assert (json_object_set_new (res, "flags", json_integer (P->flags)) >= 0); 148 | 149 | switch (tgl_get_peer_type (id)) { 150 | case TGL_PEER_USER: 151 | json_pack_user (res, P); 152 | break; 153 | case TGL_PEER_CHAT: 154 | json_pack_chat (res, P); 155 | break; 156 | case TGL_PEER_ENCR_CHAT: 157 | json_pack_encr_chat (res, P); 158 | break; 159 | case TGL_PEER_CHANNEL: 160 | json_pack_channel (res, P); 161 | break; 162 | default: 163 | assert (0); 164 | } 165 | return res; 166 | } 167 | 168 | json_t *json_pack_updates (unsigned flags) { 169 | json_t *a = json_array (); 170 | 171 | if (flags & TGL_UPDATE_CREATED) { 172 | assert (json_array_append_new (a, json_string ("created")) >= 0); 173 | } 174 | if (flags & TGL_UPDATE_DELETED) { 175 | assert (json_array_append_new (a, json_string ("deleted")) >= 0); 176 | } 177 | if (flags & TGL_UPDATE_PHONE) { 178 | assert (json_array_append_new (a, json_string ("phone")) >= 0); 179 | } 180 | if (flags & TGL_UPDATE_CONTACT) { 181 | assert (json_array_append_new (a, json_string ("contact")) >= 0); 182 | } 183 | if (flags & TGL_UPDATE_PHOTO) { 184 | assert (json_array_append_new (a, json_string ("photo")) >= 0); 185 | } 186 | if (flags & TGL_UPDATE_BLOCKED) { 187 | assert (json_array_append_new (a, json_string ("blocked")) >= 0); 188 | } 189 | if (flags & TGL_UPDATE_REAL_NAME) { 190 | assert (json_array_append_new (a, json_string ("real_name")) >= 0); 191 | } 192 | if (flags & TGL_UPDATE_NAME) { 193 | assert (json_array_append_new (a, json_string ("name")) >= 0); 194 | } 195 | if (flags & TGL_UPDATE_REQUESTED) { 196 | assert (json_array_append_new (a, json_string ("requested")) >= 0); 197 | } 198 | if (flags & TGL_UPDATE_WORKING) { 199 | assert (json_array_append_new (a, json_string ("working")) >= 0); 200 | } 201 | if (flags & TGL_UPDATE_FLAGS) { 202 | assert (json_array_append_new (a, json_string ("flags")) >= 0); 203 | } 204 | if (flags & TGL_UPDATE_TITLE) { 205 | assert (json_array_append_new (a, json_string ("title")) >= 0); 206 | } 207 | if (flags & TGL_UPDATE_ADMIN) { 208 | assert (json_array_append_new (a, json_string ("admin")) >= 0); 209 | } 210 | if (flags & TGL_UPDATE_MEMBERS) { 211 | assert (json_array_append_new (a, json_string ("members")) >= 0); 212 | } 213 | if (flags & TGL_UPDATE_ACCESS_HASH) { 214 | assert (json_array_append_new (a, json_string ("access_hash")) >= 0); 215 | } 216 | if (flags & TGL_UPDATE_USERNAME) { 217 | assert (json_array_append_new (a, json_string ("username")) >= 0); 218 | } 219 | 220 | return a; 221 | } 222 | 223 | 224 | json_t *json_pack_media (struct tgl_message_media *M) { 225 | json_t *res = json_object (); 226 | 227 | switch (M->type) { 228 | case tgl_message_media_photo: 229 | assert (json_object_set_new (res, "type", json_string ("photo")) >= 0); 230 | if (M->caption) { 231 | assert (json_object_set_new (res, "caption", json_string (M->caption)) >= 0); 232 | } 233 | break; 234 | case tgl_message_media_document: 235 | assert (json_object_set_new (res, "type", json_string ("document")) >= 0); 236 | break; 237 | case tgl_message_media_audio: 238 | assert (json_object_set_new (res, "type", json_string ("audio")) >= 0); 239 | break; 240 | case tgl_message_media_video: 241 | assert (json_object_set_new (res, "type", json_string ("video")) >= 0); 242 | break; 243 | case tgl_message_media_document_encr: 244 | assert (json_object_set_new (res, "type", json_string ("document_encr")) >= 0); 245 | break; 246 | case tgl_message_media_unsupported: 247 | assert (json_object_set_new (res, "type", json_string ("unsupported")) >= 0); 248 | break; 249 | case tgl_message_media_geo: 250 | assert (json_object_set_new (res, "type", json_string ("geo")) >= 0); 251 | assert (json_object_set_new (res, "longitude", json_real (M->geo.longitude)) >= 0); 252 | assert (json_object_set_new (res, "latitude", json_real (M->geo.latitude)) >= 0); 253 | break; 254 | case tgl_message_media_contact: 255 | assert (json_object_set_new (res, "type", json_string ("contact")) >= 0); 256 | assert (json_object_set_new (res, "phone", json_string (M->phone)) >= 0); 257 | assert (json_object_set_new (res, "first_name", json_string (M->first_name)) >= 0); 258 | assert (json_object_set_new (res, "last_name", json_string (M->last_name)) >= 0); 259 | assert (json_object_set_new (res, "user_id", json_integer (M->user_id)) >= 0); 260 | break; 261 | case tgl_message_media_webpage: 262 | assert (json_object_set_new (res, "type", json_string ("webpage")) >= 0); 263 | if (M->webpage->url) { 264 | assert (json_object_set_new (res, "url", json_string (M->webpage->url)) >= 0); 265 | } 266 | if (M->webpage->title) { 267 | assert (json_object_set_new (res, "title", json_string (M->webpage->title)) >= 0); 268 | } 269 | if (M->webpage->description) { 270 | assert (json_object_set_new (res, "description", json_string (M->webpage->description)) >= 0); 271 | } 272 | if (M->webpage->author) { 273 | assert (json_object_set_new (res, "author", json_string (M->webpage->author)) >= 0); 274 | } 275 | break; 276 | case tgl_message_media_venue: 277 | assert (json_object_set_new (res, "type", json_string ("venue")) >= 0); 278 | assert (json_object_set_new (res, "longitude", json_real (M->venue.geo.longitude)) >= 0); 279 | assert (json_object_set_new (res, "latitude", json_real (M->venue.geo.latitude)) >= 0); 280 | if (M->venue.title) { 281 | assert (json_object_set_new (res, "title", json_string (M->venue.title)) >= 0); 282 | } 283 | if (M->venue.address) { 284 | assert (json_object_set_new (res, "address", json_string (M->venue.address)) >= 0); 285 | } 286 | if (M->venue.provider) { 287 | assert (json_object_set_new (res, "provider", json_string (M->venue.provider)) >= 0); 288 | } 289 | if (M->venue.venue_id) { 290 | assert (json_object_set_new (res, "venue_id", json_string (M->venue.venue_id)) >= 0); 291 | } 292 | break; 293 | default: 294 | assert (json_object_set_new (res, "type", json_string ("unknown")) >= 0); 295 | } 296 | return res; 297 | } 298 | 299 | json_t *json_pack_typing (enum tgl_typing_status status) { 300 | json_t *res = json_object (); 301 | switch (status) { 302 | case tgl_typing_none: 303 | assert (json_object_set_new (res, "status", json_string ("doing nothing")) >= 0); 304 | break; 305 | case tgl_typing_typing: 306 | assert (json_object_set_new (res, "status", json_string ("typing")) >= 0); 307 | break; 308 | case tgl_typing_cancel: 309 | assert (json_object_set_new (res, "status", json_string ("deleting typed message")) >= 0); 310 | break; 311 | case tgl_typing_record_video: 312 | assert (json_object_set_new (res, "status", json_string ("recording video")) >= 0); 313 | break; 314 | case tgl_typing_upload_video: 315 | assert (json_object_set_new (res, "status", json_string ("uploading video")) >= 0); 316 | break; 317 | case tgl_typing_record_audio: 318 | assert (json_object_set_new (res, "status", json_string ("recording audio")) >= 0); 319 | break; 320 | case tgl_typing_upload_audio: 321 | assert (json_object_set_new (res, "status", json_string ("uploading audio")) >= 0); 322 | break; 323 | case tgl_typing_upload_photo: 324 | assert (json_object_set_new (res, "status", json_string ("uploading photo")) >= 0); 325 | break; 326 | case tgl_typing_upload_document: 327 | assert (json_object_set_new (res, "status", json_string ("uploading document")) >= 0); 328 | break; 329 | case tgl_typing_geo: 330 | assert (json_object_set_new (res, "status", json_string ("choosing location")) >= 0); 331 | break; 332 | case tgl_typing_choose_contact: 333 | assert (json_object_set_new (res, "status", json_string ("choosing contact")) >= 0); 334 | break; 335 | default: 336 | assert (json_object_set_new (res, "status", json_string ("unknown")) >= 0); 337 | break; 338 | } 339 | return res; 340 | } 341 | 342 | json_t *json_pack_service (struct tgl_message *M) { 343 | json_t *res = json_object (); 344 | switch (M->action.type) { 345 | case tgl_message_action_geo_chat_create: 346 | assert (json_object_set_new (res, "type", json_string ("geo_created")) >= 0); 347 | break; 348 | case tgl_message_action_geo_chat_checkin: 349 | assert (json_object_set_new (res, "type", json_string ("geo_checkin")) >= 0); 350 | break; 351 | case tgl_message_action_chat_create: 352 | assert (json_object_set_new (res, "type", json_string ("chat_created")) >= 0); 353 | assert (json_object_set_new (res, "title", json_string (M->action.title)) >= 0); 354 | break; 355 | case tgl_message_action_chat_edit_title: 356 | assert (json_object_set_new (res, "type", json_string ("chat_rename")) >= 0); 357 | assert (json_object_set_new (res, "title", json_string (M->action.title)) >= 0); 358 | break; 359 | case tgl_message_action_chat_edit_photo: 360 | assert (json_object_set_new (res, "type", json_string ("chat_change_photo")) >= 0); 361 | break; 362 | case tgl_message_action_chat_delete_photo: 363 | assert (json_object_set_new (res, "type", json_string ("chat_delete_photo")) >= 0); 364 | break; 365 | case tgl_message_action_chat_add_users: 366 | assert (json_object_set_new (res, "type", json_string ("chat_add_user")) >= 0); 367 | assert (json_object_set_new (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.users[0]))) >= 0); 368 | break; 369 | case tgl_message_action_chat_add_user_by_link: 370 | assert (json_object_set_new (res, "type", json_string ("chat_add_user_link")) >= 0); 371 | assert (json_object_set_new (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user))) >= 0); 372 | break; 373 | case tgl_message_action_chat_delete_user: 374 | assert (json_object_set_new (res, "type", json_string ("chat_del_user")) >= 0); 375 | assert (json_object_set_new (res, "user", json_pack_peer (tgl_set_peer_id (TGL_PEER_USER, M->action.user))) >= 0); 376 | break; 377 | case tgl_message_action_set_message_ttl: 378 | assert (json_object_set_new (res, "type", json_string ("set_ttl")) >= 0); 379 | assert (json_object_set_new (res, "ttl", json_integer (M->action.ttl)) >= 0); 380 | break; 381 | case tgl_message_action_read_messages: 382 | assert (json_object_set_new (res, "type", json_string ("read")) >= 0); 383 | assert (json_object_set_new (res, "count", json_integer (M->action.read_cnt)) >= 0); 384 | break; 385 | case tgl_message_action_delete_messages: 386 | assert (json_object_set_new (res, "type", json_string ("delete")) >= 0); 387 | assert (json_object_set_new (res, "count", json_integer (M->action.delete_cnt)) >= 0); 388 | break; 389 | case tgl_message_action_screenshot_messages: 390 | assert (json_object_set_new (res, "type", json_string ("screenshot")) >= 0); 391 | assert (json_object_set_new (res, "count", json_integer (M->action.screenshot_cnt)) >= 0); 392 | break; 393 | case tgl_message_action_flush_history: 394 | assert (json_object_set_new (res, "type", json_string ("flush")) >= 0); 395 | break; 396 | case tgl_message_action_resend: 397 | assert (json_object_set_new (res, "type", json_string ("resend")) >= 0); 398 | break; 399 | case tgl_message_action_notify_layer: 400 | assert (json_object_set_new (res, "type", json_string ("notify_layer")) >= 0); 401 | assert (json_object_set_new (res, "layer", json_integer (M->action.layer)) >= 0); 402 | break; 403 | case tgl_message_action_typing: 404 | assert (json_object_set_new (res, "type", json_string ("typing")) >= 0); 405 | assert (json_array_append_new (res, json_pack_typing (M->action.typing)) >= 0); 406 | break; 407 | case tgl_message_action_noop: 408 | assert (json_object_set_new (res, "type", json_string ("noop")) >= 0); 409 | break; 410 | case tgl_message_action_request_key: 411 | assert (json_object_set_new (res, "type", json_string ("request_key")) >= 0); 412 | break; 413 | case tgl_message_action_accept_key: 414 | assert (json_object_set_new (res, "type", json_string ("accept_key")) >= 0); 415 | break; 416 | case tgl_message_action_commit_key: 417 | assert (json_object_set_new (res, "type", json_string ("commit_key")) >= 0); 418 | break; 419 | case tgl_message_action_abort_key: 420 | assert (json_object_set_new (res, "type", json_string ("abort_key")) >= 0); 421 | break; 422 | case tgl_message_action_channel_create: 423 | assert (json_object_set_new (res, "type", json_string ("channel_created")) >= 0); 424 | assert (json_object_set_new (res, "title", json_string (M->action.title)) >= 0); 425 | break; 426 | case tgl_message_action_migrated_to: 427 | assert (json_object_set_new (res, "type", json_string ("migrated_to")) >= 0); 428 | break; 429 | case tgl_message_action_migrated_from: 430 | assert (json_object_set_new (res, "type", json_string ("migrated_from")) >= 0); 431 | break; 432 | default: 433 | assert (json_object_set_new (res, "type", json_string ("unknown")) >= 0); 434 | break; 435 | } 436 | return res; 437 | } 438 | 439 | json_t *json_pack_message (struct tgl_message *M) { 440 | json_t *res = json_object (); 441 | assert (json_object_set_new (res, "event", json_string ("message")) >= 0); 442 | //will overwriten to service, if service. 443 | 444 | assert (json_object_set_new (res, "id", json_string (print_permanent_msg_id (M->permanent_id))) >= 0); 445 | if (!(M->flags & TGLMF_CREATED)) { return res; } 446 | 447 | assert (json_object_set_new (res, "flags", json_integer (M->flags)) >= 0); 448 | 449 | if (tgl_get_peer_type (M->fwd_from_id)) { 450 | assert (json_object_set_new (res, "fwd_from", json_pack_peer (M->fwd_from_id)) >= 0); 451 | assert (json_object_set_new (res, "fwd_date", json_integer (M->fwd_date)) >= 0); 452 | } 453 | 454 | if (M->reply_id) { 455 | tgl_message_id_t msg_id = M->permanent_id; 456 | msg_id.id = M->reply_id; 457 | 458 | assert (json_object_set_new (res, "reply_id", json_string (print_permanent_msg_id (msg_id))) >= 0); 459 | } 460 | 461 | if (M->flags & TGLMF_MENTION) { 462 | assert (json_object_set_new (res, "mention", json_true ()) >= 0); 463 | } 464 | 465 | assert (json_object_set_new (res, "from", json_pack_peer (M->from_id)) >= 0); 466 | assert (json_object_set_new (res, "to", json_pack_peer (M->to_id)) >= 0); 467 | 468 | assert (json_object_set_new (res, "out", json_boolean (M->flags & TGLMF_OUT)) >= 0); 469 | assert (json_object_set_new (res, "unread", json_boolean (M->flags & TGLMF_UNREAD)) >= 0); 470 | assert (json_object_set_new (res, "service", json_boolean (M->flags & TGLMF_SERVICE)) >= 0); 471 | assert (json_object_set_new (res, "date", json_integer (M->date)) >= 0); 472 | 473 | if (!(M->flags & TGLMF_SERVICE)) { 474 | if (M->message_len && M->message) { 475 | assert (json_object_set_new (res, "text", json_string (M->message)) >= 0); 476 | } 477 | if (M->media.type && M->media.type != tgl_message_media_none) { 478 | assert (json_object_set_new (res, "media", json_pack_media (&M->media)) >= 0); 479 | } 480 | } else { 481 | assert (json_object_set_new (res, "event", json_string ("service")) >= 0); 482 | assert (json_object_set_new (res, "action", json_pack_service (M)) >= 0); 483 | } 484 | return res; 485 | } 486 | 487 | json_t *json_pack_read (struct tgl_message *M) { 488 | json_t *res = json_pack_message (M); 489 | assert (json_object_set_new (res, "event", json_string ("read")) >= 0); 490 | //this will overwrite "event":"message" to "event":"read". 491 | return res; 492 | } 493 | 494 | json_t *json_pack_user_status (struct tgl_user *U) { 495 | json_t *res = json_object (); 496 | assert (json_object_set_new (res, "user", json_pack_peer (U->id)) >= 0); 497 | struct tgl_user_status *S = &U->status; 498 | assert (json_object_set_new (res, "online", json_boolean (S->online == 1)) >= 0); 499 | assert (json_object_set_new (res, "state", json_integer (S->online)) >= 0); 500 | if (S->online > 0 || S->online == -1) { 501 | static char s[20]; 502 | str_format_time(S->when, s); 503 | assert (json_object_set_new (res, "when", json_string (s)) >= 0); 504 | } else if (S->online == 0) { 505 | assert (json_object_set(res, "when", json_string("long time ago")) >= 0); 506 | } else if (S->online == -2) { 507 | assert (json_object_set(res, "when", json_string("recently")) >= 0); 508 | } else if (S->online == -3) { 509 | assert (json_object_set(res, "when", json_string("last week")) >= 0); 510 | } else if (S->online == -4) { 511 | assert (json_object_set_new (res, "when", json_string ("last month")) >= 0); 512 | } 513 | assert (json_object_set_new (res, "event", json_string ("online-status")) >= 0); 514 | //this will overwrite "event":"message" to "event":"read". 515 | return res; 516 | } 517 | 518 | #endif 519 | -------------------------------------------------------------------------------- /json-tg.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSON_TG_H__ 2 | #define __JSON_TG_H__ 3 | #include "config.h" 4 | #ifdef USE_JSON 5 | #include 6 | #include 7 | #include 8 | json_t *json_pack_message (struct tgl_message *M); 9 | json_t *json_pack_updates (unsigned flags); 10 | json_t *json_pack_peer (tgl_peer_id_t id); 11 | json_t *json_pack_read (struct tgl_message *M); 12 | json_t *json_pack_user_status (struct tgl_user *U); 13 | #endif 14 | #endif 15 | -------------------------------------------------------------------------------- /loop.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of telegram-cli. 3 | 4 | Telegram-cli is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | Telegram-cli is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this telegram-cli. If not, see . 16 | 17 | Copyright Vitaly Valtman 2013-2015 18 | */ 19 | #ifndef __LOOP_H__ 20 | #define __LOOP_H__ 21 | #define TELEGRAM_CLI_APP_HASH "36722c72256a24c1225de00eb6a1ca74" 22 | #define TELEGRAM_CLI_APP_ID 2899 23 | 24 | int loop (void); 25 | void do_halt (int error); 26 | void write_auth_file (void); 27 | void write_state_file (void); 28 | void write_secret_chat_file (void); 29 | #endif 30 | -------------------------------------------------------------------------------- /lua-tg.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of telegram-cli. 3 | 4 | Telegram-cli is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | Telegram-cli is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this telegram-cli. If not, see . 16 | 17 | Copyright Vitaly Valtman 2013-2015 18 | */ 19 | #ifndef __LUA_TG_H__ 20 | #define __LUA_TG_H__ 21 | 22 | #include 23 | #include 24 | 25 | void lua_init (const char *file); 26 | void lua_new_msg (struct tgl_message *M); 27 | void lua_list_msg (struct tgl_message *M); 28 | void lua_our_id (tgl_peer_id_t id); 29 | void lua_secret_chat_update (struct tgl_secret_chat *U, unsigned flags); 30 | void lua_user_update (struct tgl_user *U, unsigned flags); 31 | void lua_chat_update (struct tgl_chat *C, unsigned flags); 32 | void lua_binlog_end (void); 33 | void lua_diff_end (void); 34 | void lua_do_all (void); 35 | #endif 36 | -------------------------------------------------------------------------------- /m4-ax_gcc_builtin.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_gcc_builtin.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_GCC_BUILTIN(BUILTIN) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro checks if the compiler supports one of GCC's built-in 12 | # functions; many other compilers also provide those same built-ins. 13 | # 14 | # The BUILTIN parameter is the name of the built-in function. 15 | # 16 | # If BUILTIN is supported define HAVE_. Keep in mind that since 17 | # builtins usually start with two underscores they will be copied over 18 | # into the HAVE_ definition (e.g. HAVE___BUILTIN_EXPECT for 19 | # __builtin_expect()). 20 | # 21 | # The macro caches its result in the ax_cv_have_ variable (e.g. 22 | # ax_cv_have___builtin_expect). 23 | # 24 | # The macro currently supports the following built-in functions: 25 | # 26 | # __builtin_assume_aligned 27 | # __builtin_bswap32 28 | # __builtin_bswap64 29 | # __builtin_choose_expr 30 | # __builtin___clear_cache 31 | # __builtin_clrsb 32 | # __builtin_clrsbl 33 | # __builtin_clrsbll 34 | # __builtin_clz 35 | # __builtin_clzl 36 | # __builtin_clzll 37 | # __builtin_complex 38 | # __builtin_constant_p 39 | # __builtin_ctz 40 | # __builtin_ctzl 41 | # __builtin_ctzll 42 | # __builtin_expect 43 | # __builtin_ffs 44 | # __builtin_ffsl 45 | # __builtin_ffsll 46 | # __builtin_fpclassify 47 | # __builtin_huge_val 48 | # __builtin_huge_valf 49 | # __builtin_huge_vall 50 | # __builtin_inf 51 | # __builtin_infd128 52 | # __builtin_infd32 53 | # __builtin_infd64 54 | # __builtin_inff 55 | # __builtin_infl 56 | # __builtin_isinf_sign 57 | # __builtin_nan 58 | # __builtin_nand128 59 | # __builtin_nand32 60 | # __builtin_nand64 61 | # __builtin_nanf 62 | # __builtin_nanl 63 | # __builtin_nans 64 | # __builtin_nansf 65 | # __builtin_nansl 66 | # __builtin_object_size 67 | # __builtin_parity 68 | # __builtin_parityl 69 | # __builtin_parityll 70 | # __builtin_popcount 71 | # __builtin_popcountl 72 | # __builtin_popcountll 73 | # __builtin_powi 74 | # __builtin_powif 75 | # __builtin_powil 76 | # __builtin_prefetch 77 | # __builtin_trap 78 | # __builtin_types_compatible_p 79 | # __builtin_unreachable 80 | # 81 | # Unsuppored built-ins will be tested with an empty parameter set and the 82 | # result of the check might be wrong or meaningless so use with care. 83 | # 84 | # LICENSE 85 | # 86 | # Copyright (c) 2013 Gabriele Svelto 87 | # 88 | # Copying and distribution of this file, with or without modification, are 89 | # permitted in any medium without royalty provided the copyright notice 90 | # and this notice are preserved. This file is offered as-is, without any 91 | # warranty. 92 | 93 | #serial 2 94 | 95 | AC_DEFUN([AX_GCC_BUILTIN], [ 96 | AS_VAR_PUSHDEF([ac_var], [ax_cv_have_$1]) 97 | 98 | AC_CACHE_CHECK([for $1], [ac_var], [ 99 | AC_LINK_IFELSE([AC_LANG_PROGRAM([], [ 100 | m4_case([$1], 101 | [__builtin_assume_aligned], [$1("", 0)], 102 | [__builtin_bswap32], [$1(0)], 103 | [__builtin_bswap64], [$1(0)], 104 | [__builtin_choose_expr], [$1(0, 0, 0)], 105 | [__builtin___clear_cache], [$1("", "")], 106 | [__builtin_clrsb], [$1(0)], 107 | [__builtin_clrsbl], [$1(0)], 108 | [__builtin_clrsbll], [$1(0)], 109 | [__builtin_clz], [$1(0)], 110 | [__builtin_clzl], [$1(0)], 111 | [__builtin_clzll], [$1(0)], 112 | [__builtin_complex], [$1(0.0, 0.0)], 113 | [__builtin_constant_p], [$1(0)], 114 | [__builtin_ctz], [$1(0)], 115 | [__builtin_ctzl], [$1(0)], 116 | [__builtin_ctzll], [$1(0)], 117 | [__builtin_expect], [$1(0, 0)], 118 | [__builtin_ffs], [$1(0)], 119 | [__builtin_ffsl], [$1(0)], 120 | [__builtin_ffsll], [$1(0)], 121 | [__builtin_fpclassify], [$1(0, 1, 2, 3, 4, 0.0)], 122 | [__builtin_huge_val], [$1()], 123 | [__builtin_huge_valf], [$1()], 124 | [__builtin_huge_vall], [$1()], 125 | [__builtin_inf], [$1()], 126 | [__builtin_infd128], [$1()], 127 | [__builtin_infd32], [$1()], 128 | [__builtin_infd64], [$1()], 129 | [__builtin_inff], [$1()], 130 | [__builtin_infl], [$1()], 131 | [__builtin_isinf_sign], [$1(0.0)], 132 | [__builtin_nan], [$1("")], 133 | [__builtin_nand128], [$1("")], 134 | [__builtin_nand32], [$1("")], 135 | [__builtin_nand64], [$1("")], 136 | [__builtin_nanf], [$1("")], 137 | [__builtin_nanl], [$1("")], 138 | [__builtin_nans], [$1("")], 139 | [__builtin_nansf], [$1("")], 140 | [__builtin_nansl], [$1("")], 141 | [__builtin_object_size], [$1("", 0)], 142 | [__builtin_parity], [$1(0)], 143 | [__builtin_parityl], [$1(0)], 144 | [__builtin_parityll], [$1(0)], 145 | [__builtin_popcount], [$1(0)], 146 | [__builtin_popcountl], [$1(0)], 147 | [__builtin_popcountll], [$1(0)], 148 | [__builtin_powi], [$1(0, 0)], 149 | [__builtin_powif], [$1(0, 0)], 150 | [__builtin_powil], [$1(0, 0)], 151 | [__builtin_prefetch], [$1("")], 152 | [__builtin_trap], [$1()], 153 | [__builtin_types_compatible_p], [$1(int, int)], 154 | [__builtin_unreachable], [$1()], 155 | [m4_warn([syntax], [Unsupported built-in $1, the test may fail]) 156 | $1()] 157 | ) 158 | ])], 159 | [AS_VAR_SET([ac_var], [yes])], 160 | [AS_VAR_SET([ac_var], [no])]) 161 | ]) 162 | 163 | AS_IF([test yes = AS_VAR_GET([ac_var])], 164 | [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1), 1, 165 | [Define to 1 if the system has the `$1' built-in function])], []) 166 | 167 | AS_VAR_POPDEF([ac_var]) 168 | ]) 169 | -------------------------------------------------------------------------------- /m4_ax_check_openssl.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_openssl.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Look for OpenSSL in a number of default spots, or in a user-selected 12 | # spot (via --with-openssl). Sets 13 | # 14 | # OPENSSL_INCLUDES to the include directives required 15 | # OPENSSL_LIBS to the -l directives required 16 | # OPENSSL_LDFLAGS to the -L or -R flags required 17 | # 18 | # and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately 19 | # 20 | # This macro sets OPENSSL_INCLUDES such that source files should use the 21 | # openssl/ directory in include directives: 22 | # 23 | # #include 24 | # 25 | # LICENSE 26 | # 27 | # Copyright (c) 2009,2010 Zmanda Inc. 28 | # Copyright (c) 2009,2010 Dustin J. Mitchell 29 | # 30 | # Copying and distribution of this file, with or without modification, are 31 | # permitted in any medium without royalty provided the copyright notice 32 | # and this notice are preserved. This file is offered as-is, without any 33 | # warranty. 34 | 35 | #serial 8 36 | 37 | AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL]) 38 | AC_DEFUN([AX_CHECK_OPENSSL], [ 39 | found=false 40 | AC_ARG_WITH([openssl], 41 | [AS_HELP_STRING([--with-openssl=DIR], 42 | [root of the OpenSSL directory])], 43 | [ 44 | case "$withval" in 45 | "" | y | ye | yes | n | no) 46 | AC_MSG_ERROR([Invalid --with-openssl value]) 47 | ;; 48 | *) ssldirs="$withval" 49 | ;; 50 | esac 51 | ], [ 52 | # if pkg-config is installed and openssl has installed a .pc file, 53 | # then use that information and don't search ssldirs 54 | AC_PATH_PROG([PKG_CONFIG], [pkg-config]) 55 | if test x"$PKG_CONFIG" != x""; then 56 | OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null` 57 | if test $? = 0; then 58 | OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null` 59 | OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null` 60 | found=true 61 | fi 62 | fi 63 | 64 | # no such luck; use some default ssldirs 65 | if ! $found; then 66 | ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr" 67 | fi 68 | ] 69 | ) 70 | 71 | 72 | # note that we #include , so the OpenSSL headers have to be in 73 | # an 'openssl' subdirectory 74 | 75 | if ! $found; then 76 | OPENSSL_INCLUDES= 77 | for ssldir in $ssldirs; do 78 | AC_MSG_CHECKING([for openssl/ssl.h in $ssldir]) 79 | if test -f "$ssldir/include/openssl/ssl.h"; then 80 | OPENSSL_INCLUDES="-I$ssldir/include" 81 | OPENSSL_LDFLAGS="-L$ssldir/lib" 82 | OPENSSL_LIBS="-lssl -lcrypto" 83 | found=true 84 | AC_MSG_RESULT([yes]) 85 | break 86 | else 87 | AC_MSG_RESULT([no]) 88 | fi 89 | done 90 | 91 | # if the file wasn't found, well, go ahead and try the link anyway -- maybe 92 | # it will just work! 93 | fi 94 | 95 | # try the preprocessor and linker with our new flags, 96 | # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS 97 | 98 | AC_MSG_CHECKING([whether compiling and linking against OpenSSL works]) 99 | echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \ 100 | "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD 101 | 102 | save_LIBS="$LIBS" 103 | save_LDFLAGS="$LDFLAGS" 104 | save_CPPFLAGS="$CPPFLAGS" 105 | LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS" 106 | LIBS="$OPENSSL_LIBS $LIBS" 107 | CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS" 108 | AC_LINK_IFELSE( 109 | [AC_LANG_PROGRAM([#include ], [SSL_new(NULL)])], 110 | [ 111 | AC_MSG_RESULT([yes]) 112 | $1 113 | ], [ 114 | AC_MSG_RESULT([no]) 115 | $2 116 | ]) 117 | CPPFLAGS="$save_CPPFLAGS" 118 | LDFLAGS="$save_LDFLAGS" 119 | LIBS="$save_LIBS" 120 | 121 | AC_SUBST([OPENSSL_INCLUDES]) 122 | AC_SUBST([OPENSSL_LIBS]) 123 | AC_SUBST([OPENSSL_LDFLAGS]) 124 | ]) 125 | -------------------------------------------------------------------------------- /m4_ax_check_zlib.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_zlib.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_ZLIB([action-if-found], [action-if-not-found]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro searches for an installed zlib library. If nothing was 12 | # specified when calling configure, it searches first in /usr/local and 13 | # then in /usr, /opt/local and /sw. If the --with-zlib=DIR is specified, 14 | # it will try to find it in DIR/include/zlib.h and DIR/lib/libz.a. If 15 | # --without-zlib is specified, the library is not searched at all. 16 | # 17 | # If either the header file (zlib.h) or the library (libz) is not found, 18 | # shell commands 'action-if-not-found' is run. If 'action-if-not-found' is 19 | # not specified, the configuration exits on error, asking for a valid zlib 20 | # installation directory or --without-zlib. 21 | # 22 | # If both header file and library are found, shell commands 23 | # 'action-if-found' is run. If 'action-if-found' is not specified, the 24 | # default action appends '-I${ZLIB_HOME}/include' to CPFLAGS, appends 25 | # '-L$ZLIB_HOME}/lib' to LDFLAGS, prepends '-lz' to LIBS, and calls 26 | # AC_DEFINE(HAVE_LIBZ). You should use autoheader to include a definition 27 | # for this symbol in a config.h file. Sample usage in a C/C++ source is as 28 | # follows: 29 | # 30 | # #ifdef HAVE_LIBZ 31 | # #include 32 | # #endif /* HAVE_LIBZ */ 33 | # 34 | # LICENSE 35 | # 36 | # Copyright (c) 2008 Loic Dachary 37 | # Copyright (c) 2010 Bastien Chevreux 38 | # 39 | # This program is free software; you can redistribute it and/or modify it 40 | # under the terms of the GNU General Public License as published by the 41 | # Free Software Foundation; either version 2 of the License, or (at your 42 | # option) any later version. 43 | # 44 | # This program is distributed in the hope that it will be useful, but 45 | # WITHOUT ANY WARRANTY; without even the implied warranty of 46 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 47 | # Public License for more details. 48 | # 49 | # You should have received a copy of the GNU General Public License along 50 | # with this program. If not, see . 51 | # 52 | # As a special exception, the respective Autoconf Macro's copyright owner 53 | # gives unlimited permission to copy, distribute and modify the configure 54 | # scripts that are the output of Autoconf when processing the Macro. You 55 | # need not follow the terms of the GNU General Public License when using 56 | # or distributing such scripts, even though portions of the text of the 57 | # Macro appear in them. The GNU General Public License (GPL) does govern 58 | # all other use of the material that constitutes the Autoconf Macro. 59 | # 60 | # This special exception to the GPL applies to versions of the Autoconf 61 | # Macro released by the Autoconf Archive. When you make and distribute a 62 | # modified version of the Autoconf Macro, you may extend this special 63 | # exception to the GPL to apply to your modified version as well. 64 | 65 | #serial 14 66 | 67 | AU_ALIAS([CHECK_ZLIB], [AX_CHECK_ZLIB]) 68 | AC_DEFUN([AX_CHECK_ZLIB], 69 | # 70 | # Handle user hints 71 | # 72 | [AC_MSG_CHECKING(if zlib is wanted) 73 | zlib_places="/usr/local /usr /opt/local /sw" 74 | AC_ARG_WITH([zlib], 75 | [ --with-zlib=DIR root directory path of zlib installation @<:@defaults to 76 | /usr/local or /usr if not found in /usr/local@:>@ 77 | --without-zlib to disable zlib usage completely], 78 | [if test "$withval" != no ; then 79 | AC_MSG_RESULT(yes) 80 | if test -d "$withval" 81 | then 82 | zlib_places="$withval $zlib_places" 83 | else 84 | AC_MSG_WARN([Sorry, $withval does not exist, checking usual places]) 85 | fi 86 | else 87 | zlib_places= 88 | AC_MSG_RESULT(no) 89 | fi], 90 | [AC_MSG_RESULT(yes)]) 91 | 92 | # 93 | # Locate zlib, if wanted 94 | # 95 | if test -n "${zlib_places}" 96 | then 97 | # check the user supplied or any other more or less 'standard' place: 98 | # Most UNIX systems : /usr/local and /usr 99 | # MacPorts / Fink on OSX : /opt/local respectively /sw 100 | for ZLIB_HOME in ${zlib_places} ; do 101 | if test -f "${ZLIB_HOME}/include/zlib.h"; then break; fi 102 | ZLIB_HOME="" 103 | done 104 | 105 | ZLIB_OLD_LDFLAGS=$LDFLAGS 106 | ZLIB_OLD_CPPFLAGS=$CPPFLAGS 107 | if test -n "${ZLIB_HOME}"; then 108 | LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" 109 | CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" 110 | fi 111 | AC_LANG_SAVE 112 | AC_LANG_C 113 | AC_CHECK_LIB([z], [inflateEnd], [zlib_cv_libz=yes], [zlib_cv_libz=no]) 114 | AC_CHECK_HEADER([zlib.h], [zlib_cv_zlib_h=yes], [zlib_cv_zlib_h=no]) 115 | AC_LANG_RESTORE 116 | if test "$zlib_cv_libz" = "yes" && test "$zlib_cv_zlib_h" = "yes" 117 | then 118 | # 119 | # If both library and header were found, action-if-found 120 | # 121 | m4_ifblank([$1],[ 122 | CPPFLAGS="$CPPFLAGS -I${ZLIB_HOME}/include" 123 | LDFLAGS="$LDFLAGS -L${ZLIB_HOME}/lib" 124 | LIBS="-lz $LIBS" 125 | AC_DEFINE([HAVE_LIBZ], [1], 126 | [Define to 1 if you have `z' library (-lz)]) 127 | ],[ 128 | # Restore variables 129 | LDFLAGS="$ZLIB_OLD_LDFLAGS" 130 | CPPFLAGS="$ZLIB_OLD_CPPFLAGS" 131 | $1 132 | ]) 133 | else 134 | # 135 | # If either header or library was not found, action-if-not-found 136 | # 137 | m4_default([$2],[ 138 | AC_MSG_ERROR([either specify a valid zlib installation with --with-zlib=DIR or disable zlib usage with --without-zlib]) 139 | ]) 140 | fi 141 | fi 142 | ]) 143 | -------------------------------------------------------------------------------- /mime.types: -------------------------------------------------------------------------------- 1 | tgl/mime.types -------------------------------------------------------------------------------- /parts/plugins/x-autotools.py: -------------------------------------------------------------------------------- 1 | # -*- Mode:Python; indent-tabs-mode:nil; tab-width:4 -*- 2 | 3 | """This is a modified version of snapcraft's autootools plugin. 4 | 5 | This plugin uses the common plugin keywords as well as those for "sources". 6 | For more information check the 'plugins' topic for the former and the 7 | 'sources' topic for the latter. 8 | 9 | In addition, this plugin uses the following plugin-specific keywords: 10 | 11 | - configflags: 12 | (list of strings) 13 | configure flags to pass to the build such as those shown by running 14 | './configure --help' 15 | """ 16 | 17 | import os 18 | 19 | import snapcraft 20 | 21 | 22 | class AutotoolsPlugin(snapcraft.BasePlugin): 23 | 24 | @classmethod 25 | def schema(cls): 26 | schema = super().schema() 27 | schema['properties']['configflags'] = { 28 | 'type': 'array', 29 | 'minitems': 1, 30 | 'uniqueItems': True, 31 | 'items': { 32 | 'type': 'string', 33 | }, 34 | 'default': [], 35 | } 36 | schema['properties']['artifacts'] = { 37 | 'type': 'array', 38 | 'minitems': 1, 39 | 'uniqueItems': True, 40 | 'items': { 41 | 'type': 'string', 42 | }, 43 | 'default': [], 44 | } 45 | 46 | # Inform Snapcraft of the properties associated with building. If these 47 | # change in the YAML, Snapcraft will consider the build step dirty. 48 | schema['build-properties'].extend(['configflags']) 49 | 50 | return schema 51 | 52 | def __init__(self, name, options, project): 53 | super().__init__(name, options, project) 54 | self.build_packages.append('make') 55 | 56 | def build(self): 57 | super().build() 58 | self.run(['./configure'] + self.options.configflags) 59 | self.run(['make', '-j{}'.format(self.parallel_build_count)]) 60 | for artifact in self.options.artifacts: 61 | source_path = os.path.join(self.builddir, artifact) 62 | destination_path = os.path.join(self.installdir, artifact) 63 | os.makedirs(os.path.dirname(destination_path), exist_ok=True) 64 | snapcraft.file_utils.link_or_copy( 65 | source_path, destination_path) 66 | -------------------------------------------------------------------------------- /python-tg.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of telegram-cli. 3 | 4 | Telegram-cli is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | Telegram-cli is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this telegram-cli. If not, see . 16 | 17 | Copyright Vitaly Valtman 2013-2015 18 | Copyright Vincent Castellano 2015 19 | */ 20 | #ifndef __PYTHON_TG_H__ 21 | #define __PYTHON_TG_H__ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | // Python functions 28 | void py_init (const char *file); 29 | void py_new_msg (struct tgl_message *M); 30 | void py_list_msg (struct tgl_message *M); 31 | void py_our_id (int id); 32 | void py_secret_chat_update (struct tgl_secret_chat *U, unsigned flags); 33 | void py_user_update (struct tgl_user *U, unsigned flags); 34 | void py_chat_update (struct tgl_chat *C, unsigned flags); 35 | void py_binlog_end (void); 36 | void py_diff_end (void); 37 | void py_do_all (void); 38 | 39 | // Binding functions 40 | PyObject* py_contact_list(PyObject *self, PyObject *args); 41 | PyObject* py_dialog_list(PyObject *self, PyObject *args); 42 | PyObject* py_rename_chat(PyObject *self, PyObject *args); 43 | PyObject* py_send_msg(PyObject *self, PyObject *args); 44 | PyObject* py_send_typing(PyObject *self, PyObject *args); 45 | PyObject* py_send_typing_abort(PyObject *self, PyObject *args); 46 | PyObject* py_send_photo(PyObject *self, PyObject *args); 47 | PyObject* py_send_video(PyObject *self, PyObject *args); 48 | PyObject* py_send_audio(PyObject *self, PyObject *args); 49 | PyObject* py_send_document(PyObject *self, PyObject *args); 50 | PyObject* py_send_file(PyObject *self, PyObject *args); 51 | PyObject* py_send_text(PyObject *self, PyObject *args); 52 | PyObject* py_chat_set_photo(PyObject *self, PyObject *args); 53 | PyObject* py_load_photo(PyObject *self, PyObject *args); 54 | PyObject* py_load_video(PyObject *self, PyObject *args); 55 | PyObject* py_load_video_thumb(PyObject *self, PyObject *args); 56 | PyObject* py_load_audio(PyObject *self, PyObject *args); 57 | PyObject* py_load_document(PyObject *self, PyObject *args); 58 | PyObject* py_load_document_thumb(PyObject *self, PyObject *args); 59 | PyObject* py_fwd(PyObject *self, PyObject *args); 60 | PyObject* py_fwd_media(PyObject *self, PyObject *args); 61 | PyObject* py_chat_info(PyObject *self, PyObject *args); 62 | PyObject* py_user_info(PyObject *self, PyObject *args); 63 | PyObject* py_history(PyObject *self, PyObject *args); 64 | PyObject* py_chat_add_user(PyObject *self, PyObject *args); 65 | PyObject* py_chat_del_user(PyObject *self, PyObject *args); 66 | PyObject* py_add_contact(PyObject *self, PyObject *args); 67 | PyObject* py_del_contact(PyObject *self, PyObject *args); 68 | PyObject* py_rename_contact(PyObject *self, PyObject *args); 69 | PyObject* py_search(PyObject *self, PyObject *args); 70 | PyObject* py_global_search(PyObject *self, PyObject *args); 71 | PyObject* py_mark_read(PyObject *self, PyObject *args); 72 | PyObject* py_set_profile_photo(PyObject *self, PyObject *args); 73 | PyObject* py_set_profile_name(PyObject *self, PyObject *args); 74 | PyObject* py_create_secret_chat(PyObject *self, PyObject *args); 75 | PyObject* py_create_group_chat(PyObject *self, PyObject *args); 76 | PyObject* py_delete_msg(PyObject *self, PyObject *args); 77 | PyObject* py_restore_msg(PyObject *self, PyObject *args); 78 | PyObject* py_accept_secret_chat(PyObject *self, PyObject *args); 79 | PyObject* py_send_contact(PyObject *self, PyObject *args); 80 | PyObject* py_status_online(PyObject *self, PyObject *args); 81 | PyObject* py_status_offline(PyObject *self, PyObject *args); 82 | PyObject* py_send_location(PyObject *self, PyObject *args); 83 | PyObject* py_extf(PyObject *self, PyObject *args); 84 | 85 | 86 | // Util Functions 87 | void py_add_string_field (PyObject* dict, char *name, const char *value); 88 | void py_add_string_field_arr (PyObject* list, int num, const char *value); 89 | void py_add_num_field (PyObject* dict, const char *name, double value); 90 | #endif 91 | -------------------------------------------------------------------------------- /python-types.h: -------------------------------------------------------------------------------- 1 | #ifndef __PYTHON_TYPES_H__ 2 | #define __PYTHON_TYPES_H__ 3 | 4 | #include 5 | #include 6 | 7 | typedef struct { 8 | PyObject_HEAD 9 | tgl_peer_t *peer; 10 | } tgl_Peer; 11 | 12 | typedef struct { 13 | PyObject_HEAD 14 | struct tgl_message *msg; 15 | } tgl_Msg; 16 | 17 | 18 | PyObject * tgl_Peer_FromTglPeer(tgl_peer_t *peer); 19 | PyObject * tgl_Msg_FromTglMsg(struct tgl_message *peer); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /rpm/README.md: -------------------------------------------------------------------------------- 1 | Build requirements 2 | ------------------ 3 | 4 | * lua-devel 5 | * openssl-devel 6 | * libconfig-devel 7 | * readline-devel 8 | * libevent-devel 9 | * gcc 10 | * git 11 | * rpm-build 12 | 13 | 14 | Building fresh RPMs 15 | ------------------- 16 | 17 | Install build dependencies: 18 | ``` 19 | yum install git lua-devel openssl-devel libconfig-devel readline-devel libevent-devel gcc rpm-build 20 | ``` 21 | Clone the repo: 22 | ``` 23 | git clone --recursive https://github.com/vysheng/tg.git 24 | ``` 25 | Build telegram-cli RPM: 26 | ``` 27 | cd tg/rpm 28 | ./telegram-cli-build-rpm 29 | ``` 30 | And install: 31 | ``` 32 | rpm -Uvh RPMS/$HOSTTYPE/telegram-cli-Beta-*.$HOSTTYPE.rpm 33 | ``` 34 | A SRPM will be generated at SRPMS/ 35 | -------------------------------------------------------------------------------- /rpm/SPECS/telegram-cli.spec: -------------------------------------------------------------------------------- 1 | Name: telegram-cli 2 | Version: Beta 3 | Release: 3%{?dist} 4 | Summary: Private fast and open platform for instant messaging 5 | 6 | Packager: Julio González Gil 7 | Group: Internet/Messaging 8 | License: GPL 9 | URL: https://github.com/vysheng/tg 10 | Source: telegram-cli.zip 11 | 12 | BuildRequires: lua-devel, openssl-devel, libconfig-devel, readline-devel, libevent-devel, gcc, git 13 | 14 | %description 15 | Telegram is an Open Source messaging platform for mobile, desktop focused on privacy. 16 | 17 | %prep 18 | [ -d %{name} ] && rm -Rfv %{name} 19 | git clone --recursive --depth=1 https://github.com/vysheng/tg.git telegram-cli 20 | zip -r telegram-cli.zip telegram-cli 21 | mv telegram-cli.zip %{_sourcedir} 22 | cd %{name} 23 | ./configure 24 | make %{?_smp_mflags} 25 | 26 | %install 27 | cd %{name} 28 | %{__install} -D -m0755 bin/telegram-cli %{buildroot}/usr/bin/telegram-cli 29 | %{__install} -D -m0644 server.pub %{buildroot}/etc/telegram/server.pub 30 | 31 | %files 32 | /usr/bin/telegram-cli 33 | /etc/telegram/server.pub 34 | 35 | %changelog 36 | * Wed May 13 2015 Julio González Gil (git@juliogonzalez.com) 37 | - Build was not working: Fix it to use latest available code from GitHub 38 | 39 | * Tue Feb 4 2014 Pablo Iranzo Gómez (Pablo.Iranzo@gmail.com) 40 | - Add server key to /etc/telegram/ 41 | 42 | * Sat Feb 1 2014 Pablo Iranzo Gómez (Pablo.Iranzo@gmail.com) 43 | - Initial SPEC file 44 | -------------------------------------------------------------------------------- /rpm/clean: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -rf BUILD BUILDROOT RPMS SRPMS SOURCES 3 | if [ $? -eq 0 ]; then 4 | echo "Directory cleaned up." 5 | exit 0 6 | else 7 | echo "There are errors. Check log!" 8 | exit 1 9 | fi 10 | -------------------------------------------------------------------------------- /rpm/telegram-cli-build-rpm: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | VERSION='latest' 3 | BASE_DIR=$(realpath $(dirname ${0})) 4 | cd ${BASE_DIR} 5 | ./clean 6 | if [ $? -ne 0 ]; then 7 | echo 'Could not clean rpmbuild build directories. Check log!' 8 | fi 9 | rpmbuild --define "_topdir `pwd`" -ba 'SPECS/telegram-cli.spec' 10 | if [ $? -eq 0 ]; then 11 | echo "Your packages are available at $PWD/RPMS." 12 | exit 0 13 | else 14 | echo 'There are errors. Check log!' 15 | exit 1 16 | fi 17 | -------------------------------------------------------------------------------- /server.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PUBLIC KEY----- 2 | MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6 3 | lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS 4 | an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw 5 | Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+ 6 | 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n 7 | Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB 8 | -----END RSA PUBLIC KEY----- 9 | -------------------------------------------------------------------------------- /snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: telegram-cli 2 | version: master 3 | summary: Command-line interface for Telegram 4 | description: | 5 | Command-line interface for Telegram, the mssaging app with a focus on 6 | security and speed. 7 | 8 | grade: devel 9 | confinement: strict 10 | 11 | apps: 12 | telegram-cli: 13 | command: telegram-cli 14 | plugs: [network] 15 | 16 | parts: 17 | tg: 18 | source: . 19 | plugin: autotools 20 | build-packages: 21 | - g++ 22 | - libreadline-dev 23 | - libconfig-dev 24 | - libssl-dev 25 | - lua5.2 26 | - liblua5.2-dev 27 | - libevent-dev 28 | - libjansson-dev 29 | - libpython-dev 30 | artifacts: 31 | - bin/generate 32 | - bin/telegram-cli 33 | - bin/tl-parser 34 | -------------------------------------------------------------------------------- /start-telegram-daemon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # start-engine 4 | # derived from start-memcached 5 | # 2003/2004 - Jay Bonci 6 | # This script handles the parsing of the /etc/memcached.conf file 7 | # and was originally created for the Debian distribution. 8 | # Anyone may use this little script under the same terms as 9 | # memcached itself. 10 | 11 | # a bit changed it for telegram-daemon to generate config before start (Vitaly Valtman) 12 | 13 | use POSIX qw(strftime); 14 | use strict; 15 | 16 | my $id = defined($ARGV[0]) ? $ARGV[0] : ''; 17 | my $idx = $id eq '' ? '' : " '$id'"; 18 | my $idl = ($id =~ /^\.(.*)$/ ? "-$1" : $id); 19 | 20 | my $root = ""; 21 | 22 | my $params; my $etchandle; my $etcfile = "$root/etc/telegram-daemon/telegram-daemon$id.conf"; 23 | 24 | # This script assumes that engine is located at /usr/bin/engine, and 25 | # that the pidfile is writable at /var/run/engine.pid 26 | 27 | my $engine_pfx = "$root/usr/share/telegram-daemon/bin/"; 28 | my $pidfile = "$root/var/run/telegram-daemon$id.pid"; 29 | 30 | # If we don't get a valid logfile parameter in the /etc/engine.conf file, 31 | # we'll just throw away all of our in-daemon output. We need to re-tie it so 32 | # that non-bash shells will not hang on logout. Thanks to Michael Renner for 33 | # the tip 34 | my $fd_reopened = "/dev/null"; 35 | $fd_reopened = "$root/var/log/telegram-daemon/telegram-daemon$idl.log" if -d "$root/var/log/telegram-daemon/"; 36 | 37 | sub handle_logfile 38 | { 39 | my ($logfile) = @_; 40 | $logfile = "$root/var/log/telegram-daemon/$logfile" unless $logfile =~ /\//; 41 | $fd_reopened = $logfile; 42 | } 43 | 44 | sub reopen_logfile 45 | { 46 | my ($logfile) = @_; 47 | 48 | open *STDERR, ">>$logfile"; 49 | open *STDOUT, ">>$logfile"; 50 | open *STDIN, ">>/dev/null"; 51 | chown 239, 239, $logfile; 52 | $fd_reopened = $logfile; 53 | } 54 | 55 | sub adjust_arg 56 | { 57 | my ($arg) = @_; 58 | if ($arg =~ /^newest:(.*)$/) { 59 | my @L = split /:/, $1; 60 | my $x = $arg; 61 | my $xt = 0; 62 | for my $y (@L) { 63 | my @S = stat($y); 64 | if (scalar @S && $S[9] > $xt) { 65 | $x = $y; 66 | $xt = $S[9]; 67 | } 68 | } 69 | return $x; 70 | } 71 | return $arg; 72 | } 73 | 74 | # This is set up in place here to support other non -[a-z] directives 75 | 76 | my $conf_directives = { 77 | "logfile" => \&handle_logfile, 78 | }; 79 | 80 | my %Vars = ( 81 | "execute" => "msg-search-engine", 82 | "work_dir" => "$root/var/lib/telegram-daemon" 83 | ); 84 | 85 | my $have_c = 0; 86 | my $have_l = 0; 87 | my $have_u = 0; 88 | my $have_aes = 0; 89 | 90 | if(open $etchandle, $etcfile) 91 | { 92 | foreach my $line (<$etchandle>) 93 | { 94 | $line ||= ""; 95 | $line =~ s/\#.*//g; 96 | $line =~ s/\s+$//g; 97 | $line =~ s/^\s+//g; 98 | next unless $line; 99 | next if $line =~ /^\-[h]/; 100 | 101 | if($line =~ /^[^\-]/) 102 | { 103 | my ($directive, $int, $arg) = $line =~ /^(.*?)(\s+|\s*=\s*)(.*)/; 104 | next unless $directive; 105 | if (exists $conf_directives->{$directive}) { 106 | $conf_directives->{$directive}->($arg); 107 | } else { 108 | $Vars{$directive} = $arg; 109 | } 110 | next; 111 | } 112 | 113 | $have_l = 1 if $line =~ /^-L\s/; 114 | $have_c = 1 if $line =~ /^-c\s/; 115 | $have_u = 1 if $line =~ /^-U\s/; 116 | push @$params, $line; 117 | } 118 | 119 | }else{ 120 | $params = []; 121 | } 122 | 123 | push @$params, "-U telegramd" unless($have_u); 124 | push @$params, "-L $fd_reopened" unless($have_l); 125 | push @$params, "-c config$idl" unless($have_c); 126 | $params = join " ", @$params; 127 | 128 | if(-e $pidfile) 129 | { 130 | open PIDHANDLE, "$pidfile"; 131 | my $localpid = ; 132 | close PIDHANDLE; 133 | 134 | if ($localpid && $localpid =~ /(\d+)/) { $localpid = $1; } else { $localpid = -1; } 135 | if (-d "/proc/$localpid") 136 | { 137 | print STDERR "telegram-daemon$idl is already running.\n"; 138 | exit; 139 | } else { 140 | print STDERR "removing stale $pidfile.\n"; 141 | `rm -f $pidfile`; 142 | } 143 | 144 | } 145 | 146 | if (exists $Vars{'quit'}) { 147 | print STDERR "telegram-daemon$idl disabled\n"; 148 | exit(0); 149 | } 150 | 151 | my $engine = $engine_pfx.$Vars{'execute'}; 152 | my $wdir = $Vars{'work_dir'}; 153 | chdir $wdir if -d $wdir; 154 | 155 | unless (-x $engine) { 156 | print STDERR "executable $engine not found\n"; 157 | exit(1); 158 | } 159 | 160 | unless (-d $wdir) { 161 | print STDERR "work directory $wdir not found\n"; 162 | exit(1); 163 | } 164 | 165 | for my $x ('s', 0 .. 9) { 166 | if (defined($Vars{"arg$x"})) { 167 | $params .= " ".adjust_arg($Vars{"arg$x"}); 168 | } 169 | } 170 | 171 | my $pid = fork(); 172 | 173 | 174 | 175 | if (!$pid) { 176 | reopen_logfile ($fd_reopened); 177 | chdir $wdir; 178 | open(my $fh, '>', "config$idl"); 179 | 180 | my $text = <<"END_MSG" 181 | config_directory="$wdir"; 182 | test=false; 183 | msg_num=true; 184 | binlog_enabled=true; 185 | binlog="binlog$idl.bin"; 186 | pfs_enabled=true; 187 | log_level = 0; 188 | lua_script="script$idl.lua"; 189 | END_MSG 190 | ; 191 | print $fh $text; 192 | close $fh; 193 | my $t; 194 | $t = strftime ("%Y-%m-%d %H:%M:%S %Z", localtime); 195 | print STDERR "[$t] invoking telegram-daemon$idl: $engine $params\n"; 196 | exec "$engine $params"; 197 | exit (0); 198 | } else { 199 | if (open PIDHANDLE,">$pidfile") { 200 | print PIDHANDLE $pid; 201 | close PIDHANDLE; 202 | } else { 203 | print STDERR "Can't write pidfile to $pidfile.\n"; 204 | } 205 | } 206 | 207 | -------------------------------------------------------------------------------- /telegram-cli-cygwin.patch: -------------------------------------------------------------------------------- 1 | --- tg/Makefile 2016-07-24 18:04:11.022621500 +0200 2 | +++ tg-cygwin/Makefile 2016-07-24 22:55:32.710938800 +0200 3 | @@ -4,9 +4,9 @@ 4 | LDFLAGS= -L/usr/local/lib -L/usr/lib -L/usr/lib 5 | CPPFLAGS= -I/usr/local/include -I/usr/include -I/usr/include 6 | DEFS=-DHAVE_CONFIG_H 7 | -COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter -fPIC 8 | +COMPILE_FLAGS=${CFLAGS} ${CPFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Werror -Wextra -Wno-missing-field-initializers -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb -Wno-unused-parameter 9 | EXTRA_LIBS=-ljansson -lconfig -lz -levent -lreadline -llua-5.2 -lssl -lcrypto 10 | -LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS} -ldl -lpthread -lutil 11 | +LOCAL_LDFLAGS=-ggdb -levent ${EXTRA_LIBS} -ldl -lpthread -lutil 12 | LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS} 13 | 14 | DEP=dep 15 | --- tg\loop.c Sun Jul 24 15:30:11 2016 16 | +++ tg-cygwin\loop.c Sat Jul 23 17:51:49 2016 17 | @@ -489,8 +489,9 @@ 18 | close (auth_file_fd); 19 | } 20 | 21 | -void write_secret_chat (tgl_peer_t *Peer, void *extra) { 22 | - struct tgl_secret_chat *P = (void *)Peer; 23 | +// In Cygwin's Python, _P is marco constant. So change tgl_peer_t *_P -> tgl_peer_t *_Peer 24 | +void write_secret_chat (tgl_peer_t *_Peer, void *extra) { 25 | + struct tgl_secret_chat *P = (void *)_Peer; 26 | if (tgl_get_peer_type (P->id) != TGL_PEER_ENCR_CHAT) { return; } 27 | if (P->state != sc_ok) { return; } 28 | int *a = extra; 29 | @@ -737,7 +738,8 @@ 30 | vlogprintf (E_WARNING, "Accepting incoming connection\n"); 31 | socklen_t clilen = 0; 32 | struct sockaddr_in cli_addr; 33 | - int fd = accept (efd, (struct sockaddr *)&cli_addr, &clilen); 34 | + // In Cygwin, put unsigned int in socklen_t produce warning. Add (socklen_t *) casting 35 | + int fd = accept (efd, (struct sockaddr *)&cli_addr, (socklen_t *)&clilen); 36 | 37 | assert (fd >= 0); 38 | struct bufferevent *bev = bufferevent_socket_new (TLS->ev_base, fd, 0); 39 | -------------------------------------------------------------------------------- /telegram-daemon: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### BEGIN INIT INFO 4 | # Provides: engine 5 | # Required-Start: $local_fs $syslog 6 | # Required-Stop: $local_fs $syslog 7 | # Default-Start: 2 3 4 5 8 | # Default-Stop: 0 1 6 9 | # Short-Description: KittenDB Meta Engine 10 | ### END INIT INFO 11 | 12 | # 13 | # run script for KittenDB Engine 14 | # author: kot 15 | # author: burunduk 16 | # author: burunduk 17 | # 18 | # Version: 2013-06-06 19 | # 20 | 21 | # Features added: 22 | # -- flock to avoid parallel execution 23 | # -- checks to avoid creating empty engine configuration files 24 | 25 | 26 | # a bit changed it for telegram-daemon to use different folders 27 | # and to have posiiblilities to have fake root 28 | # Vitaly Valtman 29 | 30 | ROOT="" 31 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 32 | DAEMONDIR=$ROOT/usr/share/telegram-daemon/bin 33 | DAEMONBOOTSTRAP=$ROOT/usr/share/telegram-daemon/bin/start-telegram-daemon 34 | NAME=telegram-daemon 35 | DESC="KOT's meta engine" 36 | PIDFILE=$ROOT/var/run/$NAME 37 | LOCKFILE=$ROOT/var/lock/$NAME 38 | CONFFILE=$ROOT/etc/telegram-daemon/$NAME 39 | LOCK_WAIT=5 40 | STOP_TIMEOUT=5 41 | KILL_TIMEOUT=5 42 | 43 | test -x $DAEMONDIR || exit 0 44 | test -x $DAEMONBOOTSTRAP || exit 0 45 | 46 | set -e 47 | 48 | ## Utilitary functions 49 | 50 | # Send information to stderr 51 | function echo_stderr() { 52 | echo "$*" 1>&2 53 | } 54 | 55 | # Get engine status. Returns 0 on running engine, 1 otherwise. 56 | function engine_status() { 57 | local id="$1" 58 | local pif="$PIDFILE.$id.pid" 59 | if ! [ -f "$pif" ] ; then 60 | echo "stopped" 61 | return 1 62 | fi 63 | local pid="$(<$pif)" 64 | if [ -z "$pid" ]; then 65 | echo "corrupt pid file" 66 | return 1 67 | fi 68 | if [ -d "/proc/$pid/" ]; then 69 | echo "$pid" 70 | return 0 71 | else 72 | echo "failed (pid $pid)" 73 | return 1 74 | fi 75 | } 76 | 77 | # Start engine. Usage: engine_start 78 | function engine_start() { 79 | local eid="$1" 80 | local r='' 81 | local pid='' 82 | pid="$(engine_status "$eid")" && r='ok' || r='fail' 83 | if [ "$r" == 'ok' ] ; then 84 | echo_stderr "telegram-daemon-$eid: already running ($pid)" 85 | else 86 | start-stop-daemon --start --quiet --exec $DAEMONBOOTSTRAP -- .$eid 100> /dev/null 87 | fi 88 | return 0 89 | } 90 | 91 | # Stop engine. Usage: engine_stop 92 | function engine_stop() { 93 | local eid="$1" 94 | local r='' 95 | local status="$(engine_status "$eid")" && r='ok' || r='fail' 96 | local pif="$PIDFILE.$eid.pid" 97 | if [ "$r" == 'ok' ] ; then 98 | start-stop-daemon --stop --quiet --oknodo --pidfile "$pif" 99 | local ti=0 100 | while [ $ti -lt $((10 * $STOP_TIMEOUT)) ] ; do 101 | status="$(engine_status "$eid")" && r='ok' || r='fail' 102 | if [ "$r" == 'fail' ]; then 103 | break 104 | fi 105 | sleep 0.1 106 | ti=$(($ti + 1)) 107 | done 108 | if [ "$r" == 'ok' ] ; then 109 | echo_stderr "telegram-daemon-$eid: not stopped, sending SIGKILL..." 110 | start-stop-daemon --stop --quiet --oknodo --pidfile "$pif" --signal KILL 111 | ti=0 112 | while [ $ti -lt $((10 * $KILL_TIMEOUT)) ] ; do 113 | status="$(engine_status "$eid")" && r='ok' || r='fail' 114 | if [ "$r" == 'fail' ]; then 115 | break 116 | fi 117 | sleep 0.1 118 | ti=$(($ti + 1)) 119 | done 120 | fi 121 | if [ "$r" == 'ok' ] ; then 122 | echo_stderr "telegram-daemon-$eid: not stopped with SIGKILL, giving up" 123 | return 1 124 | else 125 | if [ -f "$pif" ] ; then 126 | rm "$pif" 127 | fi 128 | echo "telegram-daemon-$eid: stopped" 129 | fi 130 | else 131 | echo_stderr "telegram-daemon-$eid: not running: $status" 132 | fi 133 | return 0 134 | } 135 | 136 | # usage: engine_disable 137 | function engine_disable() { 138 | local eid="$1" 139 | local conf="$CONFFILE.$eid.conf" 140 | [ -e "$conf" ] || return 1 # work only with existing engines 141 | if grep -E '^quit 1$' "$conf" > /dev/null ; then 142 | echo_stderr "telegram-daemon-$eid: already disabled" 143 | else 144 | echo 'quit 1' >> "$conf" 145 | fi 146 | return 0 147 | } 148 | 149 | # usage: engine_enable 150 | function engine_enable() { 151 | local eid="$1" 152 | local conf="$CONFFILE.$eid.conf" 153 | [ -e "$conf" ] || return 1 # work only with existing engines 154 | if ! grep -E '^quit' "$conf" > /dev/null ; then 155 | echo_stderr "telegram-daemon-$eid: already enabled" 156 | else 157 | sed -i~ -e '/^quit/d' -- "$conf" 158 | fi 159 | return 0 160 | } 161 | 162 | # Wait for engine's command to be completed 163 | function engine_wait() { 164 | local eid="$1" 165 | ( 166 | flock -x -w $(($LOCK_WAIT + $STOP_TIMEOUT + $KILL_TIMEOUT)) 100 || exit 1 167 | ) 100> $LOCKFILE.$eid.lock || echo "Unable to wait for $eid" 168 | return 0 169 | } 170 | 171 | # Run a single command 172 | # Only one instance of this command per engine is supposed to work 173 | function run_one() { 174 | local eid="$1" 175 | shift 176 | local command="$*" 177 | [ "${#eid}" -gt 5 ] && return 0 # avoid long engine ids 178 | ( 179 | flock -x -w $LOCK_WAIT 100 || exit 1 180 | $command "$eid" 181 | ) 100> $LOCKFILE.$eid.lock 182 | return 0 183 | } 184 | 185 | # Run commands 186 | function run() { 187 | local mode="$1" 188 | shift 189 | local command="$*" 190 | local eid='' 191 | if [ "$mode" == 'parallel' ] ; then 192 | for eid in $arguments ; do 193 | run_one "$eid" "$command" & 194 | done 195 | sleep 0.1 196 | for eid in $arguments ; do 197 | engine_wait "$eid" 198 | done 199 | else 200 | for eid in $arguments ; do 201 | run_one "$eid" "$command" 202 | done 203 | fi 204 | return 0 205 | } 206 | 207 | # Get all actual engine ids 208 | function arguments_all() { 209 | local file='' 210 | local id='' 211 | local list='' 212 | for file in $(ls $CONFFILE.?*.conf 2> /dev/null) ; do 213 | id=${file#$CONFFILE.} 214 | id=${id%.conf} 215 | list="$list $id" 216 | done 217 | for file in $(ls $PIDFILE.?*.pid 2> /dev/null) ; do 218 | id=${file#$PIDFILE.} 219 | id=${id%.pid} 220 | list="$list $id" 221 | done 222 | local f='' 223 | for f in $list ; do echo "$f" ; done | sort -u 224 | return 0 225 | } 226 | 227 | ## Commands 228 | 229 | # Start engine. 230 | function engine_command_start() { 231 | local eid="$1" 232 | engine_start "$eid" 233 | } 234 | 235 | # Stop engine. 236 | function engine_command_stop() { 237 | local eid="$1" 238 | engine_stop "$eid" 239 | } 240 | 241 | # Enable engine. 242 | function engine_command_enable() { 243 | local eid="$1" 244 | engine_enable "$eid" 245 | engine_start "$eid" 246 | } 247 | 248 | # Disable engine. 249 | function engine_command_disable() { 250 | local eid="$1" 251 | engine_disable "$eid" 252 | engine_stop "$eid" 253 | } 254 | 255 | # Restart engine. 256 | function engine_command_restart() { 257 | local eid="$1" 258 | engine_stop "$eid" 259 | echo "restarting telegram-daemon-$eid..." 260 | engine_start "$eid" 261 | } 262 | 263 | # Send signal to engine. Usage: engine_command_signal 264 | function engine_command_signal() { 265 | local id="$2" 266 | local signal="$1" 267 | local r='' 268 | local comment="$(engine_status "$id")" && r='ok' || r='fail' 269 | local res='' 270 | if [ "$r" == 'ok' ]; then 271 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE.$id.pid --signal "$signal" 272 | else 273 | echo_stderr "telegram-daemon-$id: not running: $comment" 274 | fi 275 | return 0 276 | } 277 | 278 | # Get engine status 279 | function engine_command_status() { 280 | local id="$1" 281 | local res="telegram-daemon-$id: " 282 | local r='' 283 | local pid='' 284 | pid="$(engine_status "$id")" && r='ok' || r='fail' 285 | if [ "$r" == 'ok' ]; then 286 | res="$res $(COLUMNS=10000 ps -o pid,c,stime,time,cmd --no-header --pid $pid | sed -e 's/\/usr\/share\/telegram-daemon\/bin\///')" 287 | else 288 | res="$res $pid" 289 | fi 290 | echo "$res" 291 | return 0 292 | } 293 | 294 | ## Entry point 295 | 296 | command="$1" 297 | shift 298 | 299 | arguments="$*" 300 | if [ -z "$arguments" ] ; then 301 | if [ "$command" == "status" -o "$command" == "start" -o "$command" == "rotate-logs" -o "$command" == "stop" ] ; then 302 | arguments="$(arguments_all)" 303 | fi 304 | elif [ "$arguments" == "all" ] ; then 305 | arguments="$(arguments_all)" 306 | fi 307 | if [ -z "$arguments" ] ; then 308 | echo "nothing to do" 309 | exit 0 310 | fi 311 | 312 | case "$command" in 313 | ('disable') run parallel engine_command_disable ;; 314 | ('enable') run parallel engine_command_enable ;; 315 | # 316 | ('start') run parallel engine_command_start ;; 317 | ('status') run normal engine_command_status ;; 318 | ('stop') run parallel engine_command_stop ;; 319 | # 320 | ('rotate-logs') run parallel engine_command_signal USR1 ;; 321 | # 322 | ('restart'|'force-reload') run parallel engine_command_restart ;; 323 | (*) 324 | N=/etc/init.d/$NAME 325 | echo "Usage: $N {start|stop|restart|rotate-logs|status} [|all]" >&2 326 | echo " additional commands: disable , enable , reindex (use with caution)" >&2 327 | exit 1 328 | ;; 329 | esac 330 | 331 | exit 0 332 | 333 | -------------------------------------------------------------------------------- /telegram.1: -------------------------------------------------------------------------------- 1 | .TH telegram 1 "Jun 10, 2014" "" "" 2 | .SH NAME 3 | telegram \- Command-line interface for http://telegram.org. Uses readline interface. 4 | .SH SYNOPSIS 5 | \fBtelegram\fR [\fB-hvNRfBEwW\fR] [\fB-k\fR \fIpublic-key\fR] [\fB-l\fR \fIlog-level\fR] [\fB-L\fR \fIlog-file\fR] [\fB-c\fR \fIconfig-file\fR] [\fB-p\fR \fIprefix\fR] [\fB-s\fR \fIlua-script\fR] 6 | 7 | .SH DESCRIPTION 8 | .B telegram\fP is a CLI for telegram (http://telegram.org) with an embedded lua interpreter. 9 | .PP 10 | Documentation for Telegram API is available here: http://core.telegram.org/api 11 | .PP 12 | Documentation for MTproto protocol is available here: http://core.telegram.org/mtproto 13 | 14 | .SH OPTIONS 15 | .TP 16 | .B \-h 17 | prints a help message. 18 | .TP 19 | .B \-u username 20 | specify username. 21 | .TP 22 | .B \-k public-key 23 | specify server public key. 24 | By default public key is stored in the same folder named tg-server.pub or in /etc/telegram/server.pub, if it's not, specify where to find it: 25 | .TP 26 | .B \-v 27 | verbose. 28 | .TP 29 | .B \-l [1-3] 30 | log level. 31 | .TP 32 | .B \-L log-file 33 | log net file. 34 | .TP 35 | .B \-N 36 | message num mode. 37 | .TP 38 | .B \-c config-file 39 | specify config file. 40 | .TP 41 | .B \-p prefix 42 | specify prefix. 43 | .TP 44 | .B \-R 45 | register mode. 46 | .TP 47 | .B \-f 48 | sync from start. 49 | .TP 50 | .B \-B 51 | enable binlog. 52 | .TP 53 | .B \-E 54 | disable auto accept 55 | .TP 56 | .B \-w 57 | allow weak random 58 | .TP 59 | .B \-s 60 | specify lua script. Refer to the \fBSCRIPT\fR section for more information about scripting. 61 | .TP 62 | .B \-W 63 | wait dialog list 64 | .PP 65 | All those options can be set automatically using the config file (\fI~/.telegram/config\fR). You can refer to the config.sample file that comes with the source. 66 | 67 | Example: 68 | 69 | log_level = 0; 70 | .sp 71 | msg_num = TRUE; 72 | 73 | .SH COMMANDS 74 | Client support \fBTAB\fR completion and command history. 75 | 76 | Peer refers to the name of the contact or dialog and can be accessed by \fBTAB\fR completion. 77 | For user contacts peer name is Name <\fIunderscore\fR> Lastname with all spaces changed to underscores. 78 | For chats it is it's title with all spaces changed to underscores 79 | For encrypted chats it is <\fIExсlamation mark\fR> <\fIunderscore\fR> Name <\fIunderscore\fR> Lastname with all spaces changed to underscores. 80 | 81 | If two or more peers have same name, <\fIsharp\fR>number is appended to the name. (for example \fBA_B\fR, \fBA_B#1\fR, \fBA_B#2\fR and so on) 82 | 83 | You can see message numbers (\fImsg-seqno\fR) starting client with \fB-N\fR 84 | 85 | The default download dir is \fB~/.telegram/downloads\fR. 86 | 87 | The download dir can be set in the main.c line 68 88 | 89 | #define DOWNLOADS_DIRECTORY "downloads" 90 | 91 | .SS SUPPORTED COMMANDS 92 | .PP 93 | Messaging 94 | .RS 95 | .IP \(bu 2 96 | .B msg <\fIpeer\fR> Text - sends message to this peer 97 | .IP \(bu 2 98 | .B fwd <\fIuser\fR> <\fImsg-seqno\fR> forward message to user. 99 | .IP \(bu 2 100 | .B chat_with_peer <\fIpeer\fR> starts one on one chat session with this peer. /exit or /quit to end this mode. /history to show history and /read to mark as read the messages. 101 | .IP \(bu 2 102 | .B add_contact <\fIphone_number\fR> <\fIfirst_name\fR> <\fIlast_name\fR> tries to add contact to contact-list by phone 103 | .IP \(bu 2 104 | .B rename_contact <\fIuser\fR> <\fIfirst-name\fR> <\fIlast-name\fR> tries to rename contact. If you have another device it will be a fight 105 | .IP \(bu 2 106 | .B mark_read <\fIpeer\fR> mark read all received messages with peer 107 | .IP \(bu 2 108 | .B delete_msg <\fImsg-seqno\fR> remove a message 109 | .IP \(bu 2 110 | .B status_online/status_offline \fR appear online to others or not 111 | .IP \(bu 2 112 | .B fwd <\fIpeer\fR> <\fImsg-seqno\fR> forward a message to the peer specified 113 | .RE 114 | .PP 115 | Multimedia 116 | .RS 117 | .IP \(bu 2 118 | .B send_photo <\fIpeer\fR> <\fIphoto-file-name\fR> sends photo to peer 119 | .IP \(bu 2 120 | .B send_video <\fIpeer\fR> <\fIvideo-file-name\fR> sends video to peer 121 | .IP \(bu 2 122 | .B send_text <\fIpeer\fR> <\fItext-file-name\fR> sends text file as plain messages 123 | .IP \(bu 2 124 | .B load_photo/load_video/load_video_thumb/load_document/load_document_thumb/load_audio <\fImsg-seqno\fR> loads photo/video to download dir 125 | .IP \(bu 2 126 | .B view_photo/view_video/view_video_thumbnail/view_document/view_document_thumb/view_audio <\fImsg-seqno\fR> loads photo/video to download dir and starts system default viewer (xdg-open on some system) 127 | .RE 128 | Group chat options 129 | .RS 130 | .IP \(bu 2 131 | .B chat_info <\fIchat\fR> prints info about chat 132 | .IP \(bu 2 133 | .B chat_add_user <\fIchat\fR> <\fIuser\fR> add user to chat 134 | .IP \(bu 2 135 | .B chat_del_user <\fIchat\fR> <\fIuser\fR> remove user from chat 136 | .IP \(bu 2 137 | .B rename_chat <\fIchat\fR> <\fInew-name\fR> 138 | .IP \(bu 2 139 | .B creacte_group_chat <\fIuser\fR> <\fIchat-topic\fR> creates a groupchat with user, use \fBchar_add_user\fR to add more users 140 | .RE 141 | Search 142 | .RS 143 | .IP \(bu 2 144 | .B search <\fIpeer\fR> pattern - searches pattern in messages with peer 145 | .IP \(bu 2 146 | .B global_search\fR pattern - searches pattern in all messages 147 | .RE 148 | Secret chat 149 | .RS 150 | .IP \(bu 2 151 | .B create_secret_chat <\fIuser\fR> creates secret chat with this user 152 | .IP \(bu 2 153 | .B visualize_key <\fIsecret_chat\fR> prints visualization of encryption key. You should compare it to your partner's one 154 | .RE 155 | Stats and various info 156 | .RS 157 | .IP \(bu 2 158 | .B user_info <\fIuser\fR> prints info about user 159 | .IP \(bu 2 160 | .B history <\fIpeer\fR> [\fIlimit\fR] prints history (and marks it as read). Default limit = 40 161 | .IP \(bu 2 162 | .B dialog_list\fR prints info about your dialogs 163 | .IP \(bu 2 164 | .B contact_list\fR prints info about users in your contact list 165 | .IP \(bu 2 166 | .B suggested_contact\fR prints info about contacts, you have max common friends 167 | .IP \(bu 2 168 | .B stats\fR just for debugging 169 | .IP \(bu 2 170 | .B show_license\fR prints contents of GPLv2 171 | .IP \(bu 2 172 | .B help\fR prints a help page 173 | .RE 174 | Options 175 | .RS 176 | .IP \(bu 2 177 | .B set <\fIparam\fR> <\fIparam-value\fR> Possible <\fIparam\fR> values are: 178 | .Ps 179 | .RS 180 | .IP \(bu 2 181 | \fIdebug_verbosity\fR - just as it sounds. Debug verbosity 182 | .IP \(bu 2 183 | \fIlog_level\fR - level of logging of new events. Lower is less verbose: 184 | .RS 185 | .RS 186 | .IP \(bu 2 187 | \fILevel 1\fR: prints info about read messages 188 | .IP \(bu 2 189 | \fILevel 2\fR: prints line, when somebody is typing in chat 190 | .IP \(bu 2 191 | \fILevel 3\fR: prints line, when somebody changes online status 192 | .RE 193 | .RE 194 | .IP \(bu 2 195 | \fImsg_num\fR - enables/disables numeration of messages 196 | .IP \(bu 2 197 | \fIalert\fR - enables/disables alert sound notifications 198 | .RE 199 | .RE 200 | 201 | .RS 202 | .IP \(bu 2 203 | .B quit/safe_quit \fR exit the program 204 | .RE 205 | 206 | .SH SCRIPTS 207 | You can extend the program by writting a lua script. An example script come with the source (test.lua). 208 | 209 | The callbacks available are: 210 | .IP \(bu 2 211 | on_msg_receive (msg) 212 | .IP \(bu 2 213 | on_our_id (id) 214 | .IP \(bu 2 215 | on_secret_chat_created (peer) 216 | .IP \(bu 2 217 | on_user_update (user) 218 | .IP \(bu 2 219 | on_chat_update (user) 220 | .IP \(bu 2 221 | on_get_difference_end () 222 | .IP \(bu 2 223 | on_binlog_replay_end () 224 | 225 | To get more info about the parameters of those functions you can use the \fBvardump()\fR function in the test.lua. 226 | 227 | .SH ERRORS AND TROUBLESHOOTING 228 | Report or check the Github issues (https://github.com/vysheng/tg/issues) 229 | .SH SEE ALSO 230 | .B lua(1) 231 | .B xdg-open(1) 232 | .SH AUTHOR 233 | vysheng (https://github.com/vysheng) 234 | .PP 235 | Big thanks for the help of all the people contributing on Github. 236 | .PP 237 | -------------------------------------------------------------------------------- /telegram.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file is part of telegram-cli. 3 | 4 | Telegram-cli is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | Telegram-cli is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this telegram-cli. If not, see . 16 | 17 | Copyright Vitaly Valtman 2013-2015 18 | */ 19 | 20 | #ifndef PROG_NAME 21 | #define PROG_NAME "telegram-cli" 22 | #endif 23 | 24 | #define TELEGRAM_CLI_VERSION "1.4.1" 25 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | started = 0 2 | our_id = 0 3 | 4 | function vardump(value, depth, key) 5 | local linePrefix = "" 6 | local spaces = "" 7 | 8 | if key ~= nil then 9 | linePrefix = "["..key.."] = " 10 | end 11 | 12 | if depth == nil then 13 | depth = 0 14 | else 15 | depth = depth + 1 16 | for i=1, depth do spaces = spaces .. " " end 17 | end 18 | 19 | if type(value) == 'table' then 20 | mTable = getmetatable(value) 21 | if mTable == nil then 22 | print(spaces ..linePrefix.."(table) ") 23 | else 24 | print(spaces .."(metatable) ") 25 | value = mTable 26 | end 27 | for tableKey, tableValue in pairs(value) do 28 | vardump(tableValue, depth, tableKey) 29 | end 30 | elseif type(value) == 'function' or 31 | type(value) == 'thread' or 32 | type(value) == 'userdata' or 33 | value == nil 34 | then 35 | print(spaces..tostring(value)) 36 | else 37 | print(spaces..linePrefix.."("..type(value)..") "..tostring(value)) 38 | end 39 | end 40 | 41 | print ("HI, this is lua script") 42 | 43 | function ok_cb(extra, success, result) 44 | end 45 | 46 | -- Notification code {{{ 47 | 48 | function get_title (P, Q) 49 | if (Q.type == 'user') then 50 | return P.first_name .. " " .. P.last_name 51 | elseif (Q.type == 'chat') then 52 | return Q.title 53 | elseif (Q.type == 'encr_chat') then 54 | return 'Secret chat with ' .. P.first_name .. ' ' .. P.last_name 55 | else 56 | return '' 57 | end 58 | end 59 | 60 | local lgi = require ('lgi') 61 | local notify = lgi.require('Notify') 62 | notify.init ("Telegram updates") 63 | local icon = os.getenv("HOME") .. "/.telegram-cli/telegram-pics/telegram_64.png" 64 | 65 | function do_notify (user, msg) 66 | local n = notify.Notification.new(user, msg, icon) 67 | n:show () 68 | end 69 | 70 | -- }}} 71 | 72 | function on_msg_receive (msg) 73 | if started == 0 then 74 | return 75 | end 76 | if msg.out then 77 | return 78 | end 79 | do_notify (get_title (msg.from, msg.to), msg.text) 80 | 81 | if (msg.text == 'ping') then 82 | if (msg.to.id == our_id) then 83 | send_msg (msg.from.print_name, 'pong', ok_cb, false) 84 | else 85 | send_msg (msg.to.print_name, 'pong', ok_cb, false) 86 | end 87 | return 88 | end 89 | if (msg.text == 'PING') then 90 | if (msg.to.id == our_id) then 91 | fwd_msg (msg.from.print_name, msg.id, ok_cb, false) 92 | else 93 | fwd_msg (msg.to.print_name, msg.id, ok_cb, false) 94 | end 95 | return 96 | end 97 | end 98 | 99 | function on_our_id (id) 100 | our_id = id 101 | end 102 | 103 | function on_user_update (user, what) 104 | --vardump (user) 105 | end 106 | 107 | function on_chat_update (chat, what) 108 | --vardump (chat) 109 | end 110 | 111 | function on_secret_chat_update (schat, what) 112 | --vardump (schat) 113 | end 114 | 115 | function on_get_difference_end () 116 | end 117 | 118 | function cron() 119 | -- do something 120 | postpone (cron, false, 1.0) 121 | end 122 | 123 | function on_binlog_replay_end () 124 | started = 1 125 | postpone (cron, false, 1.0) 126 | end 127 | -------------------------------------------------------------------------------- /tg-server.pub: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PUBLIC KEY----- 2 | MIIBCgKCAQEAwVACPi9w23mF3tBkdZz+zwrzKOaaQdr01vAbU4E1pvkfj4sqDsm6 3 | lyDONS789sVoD/xCS9Y0hkkC3gtL1tSfTlgCMOOul9lcixlEKzwKENj1Yz/s7daS 4 | an9tqw3bfUV/nqgbhGX81v/+7RFAEd+RwFnK7a+XYl9sluzHRyVVaTTveB2GazTw 5 | Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+ 6 | 8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n 7 | Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB 8 | -----END RSA PUBLIC KEY----- 9 | 10 | -------------------------------------------------------------------------------- /tg-test.py: -------------------------------------------------------------------------------- 1 | import tgl 2 | import pprint 3 | from functools import partial 4 | 5 | 6 | our_id = 0 7 | pp = pprint.PrettyPrinter(indent=4) 8 | 9 | binlog_done = False; 10 | 11 | def on_binlog_replay_end(): 12 | global binlog_done 13 | binlog_done = True; 14 | 15 | def on_get_difference_end(): 16 | pass 17 | 18 | def on_our_id(id): 19 | global our_id 20 | our_id = id 21 | return "Set ID: " + str(our_id) 22 | 23 | def msg_cb(success, msg): 24 | pp.pprint(success) 25 | pp.pprint(msg) 26 | 27 | HISTORY_QUERY_SIZE = 100 28 | 29 | def history_cb(msg_list, peer, success, msgs): 30 | print(len(msgs)) 31 | msg_list.extend(msgs) 32 | print(len(msg_list)) 33 | if len(msgs) == HISTORY_QUERY_SIZE: 34 | tgl.get_history(peer, len(msg_list), HISTORY_QUERY_SIZE, partial(history_cb, msg_list, peer)); 35 | 36 | 37 | def cb(success): 38 | print(success) 39 | 40 | def on_msg_receive(msg): 41 | if msg.out and not binlog_done: 42 | return; 43 | 44 | if msg.dest.id == our_id: # direct message 45 | peer = msg.src 46 | else: # chatroom 47 | peer = msg.dest 48 | 49 | pp.pprint(msg) 50 | if msg.text is not None and msg.text.startswith("!ping"): 51 | peer.send_msg("PONG! google.com", preview=False, reply=msg.id) 52 | 53 | 54 | def on_secret_chat_update(peer, types): 55 | return "on_secret_chat_update" 56 | 57 | def on_user_update(peer, what_changed): 58 | pass 59 | 60 | def on_chat_update(peer, what_changed): 61 | pass 62 | 63 | def on_loop(): 64 | pass 65 | 66 | # Set callbacks 67 | tgl.set_on_binlog_replay_end(on_binlog_replay_end) 68 | tgl.set_on_get_difference_end(on_get_difference_end) 69 | tgl.set_on_our_id(on_our_id) 70 | tgl.set_on_msg_receive(on_msg_receive) 71 | tgl.set_on_secret_chat_update(on_secret_chat_update) 72 | tgl.set_on_user_update(on_user_update) 73 | tgl.set_on_chat_update(on_chat_update) 74 | tgl.set_on_loop(on_loop) 75 | 76 | --------------------------------------------------------------------------------