├── .gitignore
├── LICENSE
├── README.md
├── tron_bot.py
├── tronapi_bot
├── __init__.py
├── constants.py
├── filters.py
├── helpers.py
├── keyboards.py
└── views.py
└── tronbot.service
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 iEXBase
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | Tron Bot
3 |
4 |
5 | ## Requirements
6 |
7 | * Python 3
8 | * pip3 install base58
9 | * pip3 install requests
10 | * pip3 install tronapi
11 | * pip3 install python-telegram-bot
12 | * pip3 install lxml
13 |
14 | ## How to use
15 |
16 | ### Settings
17 | Bot Settings are in the file tronapi_bot/constants.py:
18 |
19 | ```python
20 | BOT_NAME = ""
21 | BOT_TOKEN = ""
22 | ```
23 | ### Run on local machine
24 | ```bash
25 | > python tron_bot.py
26 | ```
27 |
28 | ### Run on server
29 | Installing and running the bot on the server
30 |
31 | #### Step 1
32 | Upload all project files to server
33 | Example: /home/iexbase/tron_bot
34 | #### Step 2
35 | Create a Systemd file for TronBot:
36 | ```
37 | sudo nano /etc/systemd/system/tronbot.service
38 | ```
39 | #### Step 3
40 | ```
41 | [Unit]
42 | Description=TronBot service
43 | After=network.target
44 |
45 | [Service]
46 | Type=idle
47 | WorkingDirectory=/home/iexbase/tron_bot
48 | User=root
49 | Group=root
50 | ExecStart=/usr/bin/python3.6 tron_bot.py
51 |
52 | [Install]
53 | WantedBy=multi-user.target
54 | ```
55 | #### Step 4
56 | ```
57 | sudo systemctl start tronbot
58 | sudo systemctl enable tronbot
59 | ```
60 | check run status
61 | ```
62 | sudo systemctl status tronbot
63 | ```
64 |
65 | ## Support and Donation
66 | * Star and/or fork this repository
67 | * TRX: TRWBqiqoFZysoAeyR1J35ibuyc8EvhUAoY
68 |
--------------------------------------------------------------------------------
/tron_bot.py:
--------------------------------------------------------------------------------
1 | # --------------------------------------------------------------------
2 | # Copyright (c) iEXBase. All rights reserved.
3 | # Licensed under the MIT License.
4 | # See License.txt in the project root for license information.
5 | # --------------------------------------------------------------------
6 |
7 | import logging
8 | from decimal import Decimal
9 |
10 | import requests
11 | import telegram
12 |
13 | from telegram import (
14 | InlineKeyboardButton,
15 | InlineKeyboardMarkup
16 | )
17 | from telegram.ext import (
18 | CommandHandler,
19 | Updater,
20 | MessageHandler,
21 | CallbackQueryHandler,
22 | run_async,
23 | Filters,
24 | ConversationHandler,
25 | RegexHandler
26 | )
27 | from tronapi import Tron
28 |
29 | from tronapi_bot import (
30 | constants,
31 | views,
32 | helpers
33 | )
34 | from tronapi_bot.helpers import (
35 | text_simple,
36 | get_contract_type,
37 | currency
38 | )
39 | from tronapi_bot.keyboards import (
40 | reply_markup_p1
41 | )
42 |
43 | # initial tron-api-python
44 | tron = Tron(
45 | full_node=constants.TRON_FULL_NODE,
46 | solidity_node=constants.TRON_SOLIDITY_NODE
47 | )
48 |
49 | # Enabled logging
50 | logging.basicConfig(
51 | level=logging.DEBUG,
52 | format=constants.LOG_FORMATTER
53 | )
54 | logger = logging.getLogger()
55 |
56 | CHOOSING, TYPING_REPLY, TYPING_CHOICE = range(3)
57 |
58 |
59 | def validate(bot, update, args):
60 | """Check TRON address"""
61 |
62 | address = ' '.join(args)
63 | bot.send_message(
64 | chat_id=update.message.chat_id,
65 | text=tron.isAddress(address)
66 | )
67 |
68 |
69 | def tx(bot, update, args):
70 | """Get transaction details"""
71 |
72 | tx_id = ''.join(args)
73 | bot.send_message(
74 | chat_id=update.message.chat_id,
75 | parse_mode=telegram.ParseMode.MARKDOWN,
76 | text=_tx_view(tx_id)
77 | )
78 |
79 |
80 | def price(bot, update):
81 | """Get the latest TRON course from CoinMarketCap"""
82 |
83 | bot.send_message(
84 | chat_id=update.message.chat_id,
85 | parse_mode=telegram.ParseMode.MARKDOWN,
86 | text=_price_view()
87 | )
88 |
89 |
90 | def accounts(bot, update):
91 | """Top 10 Accounts with large balances"""
92 |
93 | bot.send_message(
94 | chat_id=update.message.chat_id,
95 | parse_mode=telegram.ParseMode.MARKDOWN,
96 | text=_accounts_view()
97 | )
98 |
99 |
100 | def block(bot, update, args):
101 | """Get information on the block"""
102 |
103 | bot.send_message(
104 | chat_id=update.message.chat_id,
105 | parse_mode=telegram.ParseMode.MARKDOWN,
106 | text=_block_view(' '.join(args))
107 | )
108 |
109 |
110 | def balance(bot, update, args):
111 | """Get a balance at"""
112 |
113 | data = ' '.join(args).split(' ')
114 | try:
115 | info = currency(tron.trx.get_balance(data[0], True))
116 | except Exception as e:
117 | info = str(e)
118 |
119 | bot.send_message(
120 | chat_id=update.message.chat_id,
121 | parse_mode=telegram.ParseMode.MARKDOWN,
122 | text=info
123 | )
124 |
125 |
126 | def last_transactions(bot, update):
127 | """Get last 10 transactions"""
128 |
129 | data = requests.get(
130 | constants.API_TRONSCAN + '/transaction?sort=-timestamp&count=true&limit=10&start=0'
131 | ).json()
132 |
133 | keyboard = []
134 | for tx in data['data']:
135 | keyboard.append([
136 | InlineKeyboardButton(tx['hash'], callback_data=tx['hash'])
137 | ])
138 |
139 | reply_markup = InlineKeyboardMarkup(keyboard)
140 | update.message.reply_text(
141 | text='Last 10 transactions',
142 | reply_markup=reply_markup
143 | )
144 |
145 |
146 | def createaccount(bot, update):
147 | """Generate new address"""
148 |
149 | bot.send_message(
150 | chat_id=update.message.chat_id,
151 | parse_mode=telegram.ParseMode.MARKDOWN,
152 | text=_create_account_view()
153 | )
154 |
155 |
156 | def stats(bot, update):
157 | """Get statistics Blockchain TRON"""
158 |
159 | bot.send_message(
160 | chat_id=update.message.chat_id,
161 | parse_mode=telegram.ParseMode.MARKDOWN,
162 | text=_statistics_view()
163 | )
164 |
165 |
166 | def dapps(bot, update):
167 | keyboard = [
168 | [InlineKeyboardButton("TRONAccelerator Winners", callback_data='dapps_0')],
169 | [InlineKeyboardButton("Games", callback_data='dapps_games')],
170 | [InlineKeyboardButton("Exchangers", callback_data='dapps_exchangers')],
171 | [InlineKeyboardButton("Gambling", callback_data='dapps_gambling')],
172 | [InlineKeyboardButton("Collectibles", callback_data='dapps_collectibles')],
173 | [InlineKeyboardButton("Other", callback_data='dapps_other')],
174 | [InlineKeyboardButton("Statistics", callback_data='dapps_stat')]
175 | ]
176 | reply_markup = InlineKeyboardMarkup(keyboard)
177 |
178 | update.message.reply_text(
179 | parse_mode=telegram.ParseMode.MARKDOWN,
180 | text='Select a category',
181 | reply_markup=reply_markup
182 | )
183 |
184 |
185 | @run_async
186 | def start(bot, update):
187 | """The first launch of the bot"""
188 |
189 | usr_name = update.message.from_user.first_name
190 | if update.message.from_user.last_name:
191 | usr_name += ' ' + update.message.from_user.last_name
192 |
193 | text_response = views.BASE_START_TEXT.format(
194 | user_name=usr_name
195 | )
196 |
197 | update.message.reply_text(
198 | text_response,
199 | parse_mode="Markdown",
200 | reply_markup=reply_markup_p1
201 | )
202 |
203 | return CHOOSING
204 |
205 |
206 | def help(bot, update):
207 | """Assistant when working with the bot"""
208 |
209 | bot.send_message(
210 | chat_id=update.message.chat_id,
211 | parse_mode=telegram.ParseMode.MARKDOWN,
212 | text=_manual(),
213 | reply_markup=reply_markup_p1
214 | )
215 |
216 |
217 | def _manual():
218 | """Instructions and commands"""
219 | return views.HELP_VIEW
220 |
221 |
222 | def _statistics_view():
223 | """TRON detailed statistics template"""
224 |
225 | base = requests.get(constants.API_TRONSCAN + '/stats/overview?limit=1').json()
226 | nodes = requests.get(constants.SERVER_TRON_API + '/node/nodemap?total=1').json()
227 | detail = base['data'][-1]
228 |
229 | text = views.STATS_VIEW.format(
230 | nodes=str(nodes['total']),
231 | height=str(detail['totalBlockCount']),
232 | total_tx=str(detail['totalTransaction']),
233 | total_accounts=str(detail['totalAddress']),
234 | new_block_height=str(detail['newBlockSeen']),
235 | new_accounts=str(detail['newAddressSeen']),
236 | new_tx=str(detail['newTransactionSeen']),
237 | time=helpers.date_format(detail['date'])
238 | )
239 | return text
240 |
241 |
242 | def _create_account_view():
243 | """Template for creating a new address"""
244 |
245 | result = tron.create_account
246 | text = views.CREATE_ACCOUNT.format(
247 | address=result.address.base58,
248 | privateKey=result.private_key,
249 | publicKey=result.public_key
250 | )
251 |
252 | return text
253 |
254 |
255 | def _block_view(block_id):
256 | """Template for getting the details of the block
257 |
258 | Args:
259 | block_id (str): Block ID (example: latest, 123444, hash)
260 |
261 | """
262 |
263 | # If no block number is specified
264 | if not block_id:
265 | block_id = 'latest'
266 |
267 | try:
268 | result = tron.trx.get_block(block_id)
269 |
270 | header = result['block_header']['raw_data']
271 | text = views.BLOCK_VIEW.format(
272 | id=result['blockID'],
273 | height=str(header['number']),
274 | time=helpers.date_format(header['timestamp']),
275 | count=str(len(result['transactions'])),
276 | parent=header['parentHash'],
277 | version=str(header['version']),
278 | witness=tron.address.from_hex(header['witness_address']).decode("utf-8")
279 | )
280 | return text
281 | except Exception:
282 | return {
283 | 'text': 'Sorry, block not found',
284 | 'reply_markup': None
285 | }
286 |
287 |
288 | def _accounts_view():
289 | """Template for getting information about TOP 10 addresses with large balances"""
290 |
291 | data = requests.get(
292 | constants.API_TRONSCAN + '/account/list?sort=-balance&limit=10&start=0'
293 | ).json()['data']
294 |
295 | text = ''
296 | for account in data:
297 | text += views.ACCOUNTS_VIEW.format(
298 | address=account['address'],
299 | balance=currency(tron.fromSun(account['balance']))
300 | )
301 | return text
302 |
303 |
304 | def _price_view():
305 | """Template for get the current exchange rate and cryptocurrency volumes TRON"""
306 |
307 | data = requests.get(constants.URL_COINMARKET_API_TRON).json()['data']
308 | data_usd = data['quotes']['USD']
309 | data_btc = data['quotes']['BTC']
310 |
311 | return views.PRICE_VIEW.format(
312 | price='{:.3f}'.format(data_usd['price']),
313 | price_btc='{:.8f}'.format(data_btc['price']),
314 | rank=data['rank'],
315 | market_cap=currency(data_usd["market_cap"]),
316 | volume_24h=currency(data_usd["volume_24h"])
317 | )
318 |
319 |
320 | def _tx_view(tx_id):
321 | """Template for obtaining transaction details
322 |
323 | Args:
324 | tx_id (str): Transaction ID
325 |
326 | """
327 |
328 | data = requests.get(constants.API_TRONSCAN + "/transaction-info?hash=" + tx_id).json()
329 | text = "Sorry, the transaction could not be found."
330 |
331 | token = 'TRX'
332 | amount = 0
333 | contract_type = get_contract_type(data['contractType'])
334 |
335 | if data['contractType'] == 1:
336 | amount = tron.fromSun(data['contractData']['amount'])
337 | elif data['contractType'] == 44:
338 | amount = tron.fromSun(data['contractData']['quant'])
339 | elif data['contractType'] == 4:
340 | amount = tron.fromSun(data['contractData']['votes'][0]['vote_count'])
341 | token = 'TP'
342 | elif data['contractType'] == 11:
343 | amount = tron.fromSun(data['contractData']['frozen_balance'])
344 | else:
345 | if 'amount' in data['contractData']:
346 | amount = data['contractData']['amount']
347 |
348 | if data['contractType'] not in [4, 12, 31]:
349 | if 'token' in data['contractData']:
350 | token = data['contractData']['token']
351 |
352 | # Статус транзакции
353 | status = "UNCONFIRMED"
354 | if data['confirmed']:
355 | status = "CONFIRMED"
356 |
357 | text = views.TX_VIEW.format(
358 | hash=str(data['hash']),
359 | status=status,
360 | block=str(data['block']),
361 | time=helpers.date_format(data['timestamp']),
362 | owner_address=data['ownerAddress'],
363 | to_address=data['toAddress'],
364 | value=currency(amount),
365 | contract_type=contract_type,
366 | token=token
367 | )
368 |
369 | return text
370 |
371 |
372 | def callback_data(bot, update):
373 | query = update.callback_query
374 |
375 | if query.data in constants.DAPPS_CAT:
376 | result = requests.get(helpers.dapps_category(query.data)).json()
377 |
378 | text = ''
379 | for item in result['data']['data']:
380 |
381 | text += views.DAPP_PREVIEW.format(
382 | name=helpers.format_html(item['name']),
383 | tagline=helpers.format_html(item['tagline']),
384 | version=str(item['ver']),
385 | developer=helpers.format_html(item['developer']),
386 | total=str(item['totalTransaction'])
387 | )
388 |
389 | bot.send_message(
390 | text=text,
391 | chat_id=query.message.chat_id,
392 | parse_mode=telegram.ParseMode.MARKDOWN
393 | )
394 |
395 | if query.data in ['dapps_stat']:
396 | total = requests.get(constants.DAPPS_API + '/statistic/total').json()['data']
397 | info = requests.get(constants.DAPPS_API + '/statistic/cate/info').json()
398 |
399 | text = views.DAPP_STAT.format(
400 | total=helpers.format_price(total['dappCount']),
401 | dau=helpers.format_price(total['dau']),
402 | transactions=helpers.format_price(total['transactionCount']),
403 | volume=helpers.format_price(total['amount']),
404 | smart_contract=helpers.format_price(total['contractCount']),
405 | )
406 |
407 | for item in info['data']:
408 | text += views.DAPP_STAT_CAT.format(
409 | category=helpers.get_dapp_categories(item['category']),
410 | dapp_count=helpers.format_price(item['dappCount']),
411 | mau=helpers.format_price(item['mau']),
412 | transactions=helpers.format_price(item['transactionCount']),
413 | smart_contract=helpers.format_price(item['contractCount']),
414 | )
415 |
416 | bot.send_message(
417 | text=text,
418 | chat_id=query.message.chat_id,
419 | parse_mode=telegram.ParseMode.MARKDOWN
420 | )
421 |
422 | if len(query.data) == 64:
423 | bot.edit_message_text(
424 | text=_tx_view(query.data),
425 | chat_id=query.message.chat_id,
426 | parse_mode=telegram.ParseMode.MARKDOWN,
427 | message_id=query.message.message_id
428 | )
429 |
430 |
431 | @run_async
432 | def filter_text_input(bot, update):
433 | usr_msg_text = update.message.text
434 | dict_to_request = text_simple(usr_msg_text)
435 |
436 | # Get transaction information by ID
437 | if dict_to_request == 'transaction':
438 | update.message.reply_text(
439 | parse_mode=telegram.ParseMode.MARKDOWN,
440 | text=_tx_view(usr_msg_text)
441 | )
442 | # Get top 10 accounts
443 | elif dict_to_request == 'topaccounts':
444 | update.message.reply_text(
445 | parse_mode=telegram.ParseMode.MARKDOWN,
446 | text=_accounts_view()
447 | )
448 | # Get lasted TRON course
449 | elif dict_to_request == 'price':
450 | update.message.reply_text(
451 | parse_mode=telegram.ParseMode.MARKDOWN,
452 | text=_price_view()
453 | )
454 | # Create new account
455 | elif dict_to_request == 'createaccount':
456 | update.message.reply_text(
457 | parse_mode=telegram.ParseMode.MARKDOWN,
458 | text=_create_account_view()
459 | )
460 | # Get stats
461 | elif dict_to_request == 'stats':
462 | update.message.reply_text(
463 | parse_mode=telegram.ParseMode.MARKDOWN,
464 | text=_statistics_view()
465 | )
466 | else:
467 | update.message.reply_text(
468 | text='You did not fill out all the fields, try again. /help',
469 | reply_markup=None
470 | )
471 |
472 | return CHOOSING
473 |
474 |
475 | def error(bot, update, error):
476 | """Log Errors caused by Updates."""
477 | logger.warning('Update "%s" caused error "%s"', update, error)
478 |
479 |
480 | def main():
481 | # Run the TRON bot
482 |
483 | # We create EventHandler and we transfer a token.
484 | updater = Updater(constants.BOT_TOKEN)
485 |
486 | # Get the dispatcher to register handlers
487 | dp = updater.dispatcher
488 |
489 | # callback query
490 | updater.dispatcher.add_handler(CallbackQueryHandler(callback_data))
491 |
492 | start_handler = ConversationHandler(
493 | entry_points=[CommandHandler('start', start)],
494 |
495 | states={
496 | CHOOSING: [
497 | RegexHandler(
498 | '^(Create Account|Price|Stats|Top Accounts)$',
499 | filter_text_input
500 | ),
501 |
502 | RegexHandler(
503 | '^(Last Transactions)$',
504 | last_transactions
505 | ),
506 |
507 | RegexHandler(
508 | '^[0-9a-zA-Z]{64}$',
509 | filter_text_input
510 | ),
511 | ]
512 | },
513 |
514 | fallbacks=[
515 | RegexHandler('^Help', help)
516 | ]
517 | )
518 |
519 | # commands
520 | dp.add_handler(start_handler)
521 | dp.add_handler(CommandHandler('help', help))
522 | dp.add_handler(CommandHandler('tx', tx, pass_args=True))
523 | dp.add_handler(CommandHandler("validate", validate, pass_args=True))
524 | dp.add_handler(CommandHandler("price", price))
525 | dp.add_handler(CommandHandler("block", block, pass_args=True))
526 | dp.add_handler(CommandHandler("balance", balance, pass_args=True))
527 | dp.add_handler(CommandHandler("accounts", accounts))
528 | dp.add_handler(CommandHandler("lasttransactions", last_transactions))
529 | dp.add_handler(CommandHandler("createaccount", createaccount))
530 | dp.add_handler(CommandHandler("stats", stats))
531 | dp.add_handler(CommandHandler('dapps', dapps))
532 |
533 | # messages
534 | # dp.add_handler(MessageHandler(Filters.text, filter_text_input))
535 |
536 | # log all errors
537 | dp.add_error_handler(error)
538 |
539 | # Run the bot
540 | updater.start_polling()
541 |
542 | # Run the bot until the you presses Ctrl-C or the process receives SIGINT,
543 | # SIGTERM or SIGABRT. This should be used most of the time, since
544 | # start_polling() is non-blocking and will stop the bot gracefully.
545 | updater.idle()
546 |
547 |
548 | if __name__ == '__main__':
549 | main()
550 |
--------------------------------------------------------------------------------
/tronapi_bot/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iexbase/tron-bot/dd088bd6dedaca19f1ac6a389ba3bc1013b0bbfc/tronapi_bot/__init__.py
--------------------------------------------------------------------------------
/tronapi_bot/constants.py:
--------------------------------------------------------------------------------
1 | # --------------------------------------------------------------------
2 | # Copyright (c) iEXBase. All rights reserved.
3 | # Licensed under the MIT License.
4 | # See License.txt in the project root for license information.
5 | # --------------------------------------------------------------------
6 |
7 | # To work with telegram bot
8 | BOT_NAME = ""
9 | BOT_TOKEN = ""
10 |
11 | # To work with tronapi
12 | TRON_FULL_NODE = "https://api.trongrid.io"
13 | TRON_SOLIDITY_NODE = "https://api.trongrid.io"
14 |
15 | SERVER_TRON_API = 'https://server.tron.network/api/v2'
16 | API_TRONSCAN = 'https://apilist.tronscan.org/api'
17 |
18 | DAPPS_API = 'https://tron.app/dh/dapp/common'
19 | DAPPS_CAT = [
20 | 'dapps_0',
21 | 'dapps_games',
22 | 'dapps_exchangers',
23 | 'dapps_gambling',
24 | 'dapps_collectibles',
25 | 'dapps_other'
26 | ]
27 |
28 |
29 | # For courses
30 | URL_COINMARKET_API_TRON = "https://api.coinmarketcap.com/v2/ticker/1958?convert=BTC"
31 |
32 | # Logging format
33 | LOG_FORMATTER = "%(asctime)s - %(levelname)s - %(name)s - %(message)s"
34 |
--------------------------------------------------------------------------------
/tronapi_bot/filters.py:
--------------------------------------------------------------------------------
1 | # --------------------------------------------------------------------
2 | # Copyright (c) iEXBase. All rights reserved.
3 | # Licensed under the MIT License.
4 | # See License.txt in the project root for license information.
5 | # --------------------------------------------------------------------
6 |
7 |
--------------------------------------------------------------------------------
/tronapi_bot/helpers.py:
--------------------------------------------------------------------------------
1 | # --------------------------------------------------------------------
2 | # Copyright (c) iEXBase. All rights reserved.
3 | # Licensed under the MIT License.
4 | # See License.txt in the project root for license information.
5 | # --------------------------------------------------------------------
6 |
7 | import locale
8 | import lxml.html
9 | import lxml.html.clean
10 | from datetime import datetime
11 |
12 | from tronapi_bot.constants import DAPPS_API
13 |
14 | locale.setlocale(locale.LC_ALL, '')
15 |
16 |
17 | def format_price(num):
18 | if num >= 1000000000:
19 | return '{:.5f}'.format(num / 1000000000) + 'k'
20 | elif num >= 1000000:
21 | return '{:.3f}'.format(num / 1000000) + 'k'
22 | elif num >= 1000:
23 | return '{:.2f}'.format(num / 1000) + 'k'
24 |
25 | return num
26 |
27 |
28 | def currency(amount):
29 | return str(locale.currency(amount, grouping=True)).replace('$', '').replace('?', '')
30 |
31 |
32 | def format_html(text):
33 | result = lxml.html.fromstring(text)
34 | cleaner = lxml.html.clean.Cleaner(style=True)
35 | result = cleaner.clean_html(result)
36 |
37 | return result.text_content()
38 |
39 |
40 | def dapps_category(categoty: str):
41 | if categoty == 'dapps_0':
42 | return DAPPS_API + '/list/bonus?category=-1&start=0&limit=10'
43 | elif categoty == 'dapps_games':
44 | return DAPPS_API + '/list?category=1&start=0&limit=10'
45 | elif categoty == 'dapps_exchangers':
46 | return DAPPS_API + '/list?category=2&start=0&limit=10'
47 | elif categoty == 'dapps_gambling':
48 | return DAPPS_API + '/list?category=5&start=0&limit=10'
49 | elif categoty == 'dapps_collectibles':
50 | return DAPPS_API + '/list?category=3&start=0&limit=10'
51 | elif categoty == 'dapps_other':
52 | return DAPPS_API + '/list?category=0&start=0&limit=10'
53 |
54 |
55 | def date_format(timestamp):
56 | return datetime.fromtimestamp(timestamp / 1000).strftime('%d-%m-%Y, %H:%M')
57 |
58 |
59 | def text_simple(usr_msg_text):
60 | if len(usr_msg_text) == 64:
61 | return 'transaction'
62 |
63 | return str(usr_msg_text).replace(' ', '').lower()
64 |
65 |
66 | def get_contract_type(t: int):
67 | if t == 1:
68 | return 'Transfer'
69 | elif t == 2:
70 | return 'Transfer Asset'
71 | elif t == 4:
72 | return 'Vote'
73 | elif t == 6:
74 | return 'Create'
75 | elif t == 9:
76 | return 'Participate'
77 | elif t == 11:
78 | return 'Freeze'
79 | elif t == 12:
80 | return 'Unfreeze'
81 | elif t == 44:
82 | return 'Exchange'
83 | elif t == 31:
84 | return 'Trigger Smart Contract'
85 | else:
86 | return 'Unregistred Name'
87 |
88 |
89 | def get_dapp_categories(i: int):
90 | if i == 0:
91 | return 'Other'
92 | elif i == 1:
93 | return 'Games'
94 | elif i == 2:
95 | return 'Exchanges'
96 | elif i == 3:
97 | return 'Collectibles'
98 | elif i == 5:
99 | return 'Gambling'
100 |
--------------------------------------------------------------------------------
/tronapi_bot/keyboards.py:
--------------------------------------------------------------------------------
1 | # --------------------------------------------------------------------
2 | # Copyright (c) iEXBase. All rights reserved.
3 | # Licensed under the MIT License.
4 | # See License.txt in the project root for license information.
5 | # --------------------------------------------------------------------
6 |
7 | from telegram import KeyboardButton, ReplyKeyboardMarkup
8 |
9 | keyboard_p1 = [
10 | [
11 | KeyboardButton("Top Accounts"),
12 | KeyboardButton("Price"),
13 | KeyboardButton("Stats")
14 | ],
15 | [KeyboardButton("Create Account")]
16 | ]
17 | reply_markup_p1 = ReplyKeyboardMarkup(keyboard_p1, True, False)
18 |
--------------------------------------------------------------------------------
/tronapi_bot/views.py:
--------------------------------------------------------------------------------
1 | # --------------------------------------------------------------------
2 | # Copyright (c) iEXBase. All rights reserved.
3 | # Licensed under the MIT License.
4 | # See License.txt in the project root for license information.
5 | # --------------------------------------------------------------------
6 |
7 | BASE_START_TEXT = ("""
8 | Hello {user_name}!. Welcome to TronBot
9 |
10 | /help - Assistant to work with the bot
11 | """)
12 |
13 |
14 | HELP_VIEW = ("""
15 | @iEXTronBot - Telegram bot that helps you with send, find data in Blockchain TRON
16 |
17 | *Commands*:
18 | /start - Start Bot
19 | /createaccount - Generate new TRON address
20 | /stats - Substrate statistics
21 | /dapps - Dapps projects
22 | /lasttransactions - Last 10 transactions
23 | /price - Actual course
24 | /accounts - TOP 10 Accounts
25 | /validate {address} - Validate address
26 | /block {id|hash} - Get information about the block
27 | /tx {hash} - Get information about the transaction
28 | /balance {address} - Getting balance at
29 |
30 | *Supports*
31 | - TRX: TRWBqiqoFZysoAeyR1J35ibuyc8EvhUAoY'
32 |
33 | """)
34 |
35 | PRICE_VIEW = ("""
36 | *Price:* {price}
37 | *Price BTC: * {price_btc}
38 | *Global Rank:* {rank}
39 | *Market Cap:* {market_cap}
40 | *24h Volume:* {volume_24h}
41 | """)
42 |
43 |
44 | ACCOUNTS_VIEW = ("""
45 | *Address* {address}
46 | *Balance TRX* {balance}
47 | ---------------------
48 | """)
49 |
50 |
51 | BLOCK_VIEW = ("""
52 | *Hash:* {id}
53 | -----------------------------
54 | *Height:* {height}
55 | *Time:* {time}
56 | *Transactions:* {count} txs
57 | *Parent Hash:* {parent}
58 | *Version*: {version}
59 | *Witness address*: {witness}
60 |
61 |
62 | """)
63 |
64 | STATS_VIEW = ("""
65 | *Online Nodes:* {nodes}
66 | *Block Height:* {height}
67 | *Total Transactions:* {total_tx}
68 | *Total Accounts:* {total_accounts}
69 |
70 | *New Blocks height:* {new_block_height}
71 | *New Accounts:* {new_accounts}
72 | *New Transactions:* {new_tx}
73 | ------------
74 | *Current time:* {time}
75 |
76 | """)
77 |
78 | TX_VIEW = ("""
79 | *Hash:* {hash}
80 | *Status:* {status}
81 | *Block:* {block}
82 | *Time:* {time}
83 | *Contract Type*: {contract_type}
84 |
85 |
86 | *Owner Address:* {owner_address}
87 | *Contract Address:* {to_address}
88 | *Value:* {value} {token}
89 |
90 | """)
91 |
92 | CREATE_ACCOUNT = ("""
93 |
94 | *Address:* {address}
95 | --------------
96 | *Private key:* {privateKey}
97 | --------------
98 | *Public key:* {publicKey}
99 | """)
100 |
101 |
102 | DAPP_PREVIEW = ("""
103 | *Name:* {name}
104 | *Tagline:* {tagline}
105 | *Version:* {version}
106 | *Developer:* {developer}
107 | *Total transaction* {total}
108 | -------------------------
109 | """)
110 |
111 |
112 | DAPP_STAT = ("""
113 | *Dapp statistics*
114 | Stats are updated daily. Check back often to see the progress and development of the DApp ecosystem.
115 |
116 | *Total DApps:* {total}
117 | *Daily active users:*: {dau}
118 | *24 hr transactions:* {transactions}
119 | *24 hr volume (TRX):* {volume}
120 | *Smart contracts:* {smart_contract}
121 |
122 | *Statistics by category:*
123 | """)
124 |
125 |
126 | DAPP_STAT_CAT = ("""
127 | *Category:* {category}
128 | *Total DApps:* {dapp_count}
129 | *Daily active users:* {mau}
130 | *24 hr transactions:* {transactions}
131 | *Smart contract:* {smart_contract}
132 | ---------------------------------
133 | """)
134 |
--------------------------------------------------------------------------------
/tronbot.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=TronBot service
3 | After=network.target
4 |
5 | [Service]
6 | Type=idle
7 | WorkingDirectory=/home/iexbase/tron_bot
8 | User=root
9 | Group=root
10 | ExecStart=/usr/bin/python3.6 tron_bot.py
11 |
12 | [Install]
13 | WantedBy=multi-user.target
14 |
--------------------------------------------------------------------------------