自己动手写一个获取当日传播预测的Telegram Bot
本文最后更新于 153 天前,其中的信息可能已经有所发展或是发生改变。
本文旨在分享搭建一个获取当日信号传输预测的Telegram Bot,不支持用来实施违法犯罪行为

前言:感谢 huige(@huige233) , acolaen (@nealoca) ,Neo_Chen(BU4AK)(@Neo_Chen) 在搭建此Bot时的帮助,也感谢友站ibcl博主为本人提供了搭建Telegram Bot来获取当日传播预测的想法

一、传播预测图的获取

作为一名HAM,每日信号传播的预测对于选一个好的波段来与友台通联是十分重要的,然而我们无法做到像各个气象局那样能够直接从卫星获得图像来分析当日传播情况,也没有那个时间,所以我们只能靠着别人每日更新的方式来获得传播预测图

那么经过Google,我们有以下两个方式来获得当日的传播预测

第一种:来自 www.hamqsl.com 上的每日传播预测图

站长是真的用心地每天支出很多为我们免费提供传播预测,真的很感谢

以下是其提供的服务列表及其地址:

HF & VHF
Selectable SN
Selectable 304A
Band
Condition
Calculations
EME Deg
Selectable MUF
Horizontal
Selectable
Solar Images
Black Only
No Transparent
https://www.hamqsl.com/solarn0nbh.php
No Band
Condition
Calculations
Large Vertical
Selectable 304A
19 Selectable
Solar Images
Black Only
No Transparent
https://www.hamqsl.com/solarpic.php
HF & VHF
Band
Condition
Calculations
Large Vertical
Selectable 304A
EME Deg
Selectable MUF
Black Only
No Transparent
https://www.hamqsl.com/solarvhf.php
No Band
Condition
Calculations
Small Vertical
Selectable 304A
Multi-Color
& Transparent
https://www.hamqsl.com/solar.php
No Band
Condition
Calculations
Small Vertical
Selectable 304A
Multi-Color
& Transparent
https://www.hamqsl.com/solarsmall.php
No Band
Condition
Calculations
Small Vertical
Limited Data
Multi-Color
& Transparent
https://www.hamqsl.com/solarbrief.php
Only Band
Condition
Calculations
Small Vertical
Multi-Color
& Transparent
https://www.hamqsl.com/solarbc.php
Band
Condition
Calculations
Small Vertical
Selectable 304A
Multi-Color
& Transparent
https://www.hamqsl.com/solar100sc.php
Band
Condition
Calculations
Large Vertical
Selectable 304A
Multi-Color
& Transparent
https://www.hamqsl.com/solar2.php
No Band
Condition
Calculations
Horizontal
Selectable 304A
19 Selectable
Solar Images
Black Only
No Transparent
https://www.hamqsl.com/solarpich.php
Band
Condition
Calculations
Selectable
Europe K-Ind
tromso &
dombas
Selectable 304A
19 Selectable
Solar Images
Black Only
No Transparent
https://www.hamqsl.com/solar101pic.php
HF & VHF
Selectable
Europe K-Ind
tromso &
dombas
Selectable 304A
Band
Condition
Calculations
EME Deg
Selectable MUF
Horizontal
Black Only
No Transparent
https://www.hamqsl.com/solar101vhf.php
HF & VHF
Selectable
Europe K-Ind
tromso &
dombas
Selectable 304A
Band
Condition
Calculations
EME Deg
Selectable MUF
Horizontal
Black Only
No Transparent
https://www.hamqsl.com/solar101vhfper.php
HF & VHF
Selectable
Europe K-Ind
tromso &
dombas
Selectable 304A
Band
Condition
Calculations
EME Deg
Selectable MUF
Horizontal
19 Selectable
Solar Images
Black Only
No Transparent
https://www.hamqsl.com/solar101vhfpic.php
Band
Condition
Calculations
Selectable
Europe K-Ind
tromso &
dombas
Selectable 304A
Multi-Color
& Transparent
https://www.hamqsl.com/solar101sc.php
No Band
Condition
Calculations
Horizontal
Selectable 304A
19 Selectable
Solar Images
Black Only
No Transparent
https://www.hamqsl.com/solarsun.php
No Band
Condition
Calculations
Horizontal
304A @ EVE only
Solar Flux
Sunspot No.
Graph
Last 30 days
Black Only
No Transparent
https://www.hamqsl.com/solargraph.php
No Band
Condition
Calculations
Horizontal
171A & 304A
@ EVE only
Solar Flux
Sunspot No.
11 MUF
readings
Graph
Last 30 days
Black Only
No Transparent
https://www.hamqsl.com/marston.php
No Band
Condition
Calculations
Horizontal
Selectable 304A
Current World
Sunlight Map
Solar Flux
Sunspot No.
11 MUF
readings
Black Only
No Transparent
https://www.hamqsl.com/solarmuf.php
No Band
Condition
Calculations
Selectable 304A
Current World
Sunlight Map
No Color
No Transparent
https://www.hamqsl.com/solarmap.php
No Band
Condition
Calculations
Selectable 304A
Current World
Sunlight Globe
No Color
No Transparent
https://www.hamqsl.com/solarglobe.php
No Band
Condition
Calculations
Selectable 304A
Current World
Moon View
of Globe
EME Deg
No Color
No Transparent
https://www.hamqsl.com/moonglobe.php
No Band
Condition
Calculations
Selectable Image
Selectable 304A
Current Solar
System View
No Color
No Transparent
https://www.hamqsl.com/solarsystem.php
后期将会翻译左侧栏内容

第二种:来自MUF(3000km) (kc2g.com)

在这个网站上,提供了MUF,foF2(临界频率),eSSN等数据,很方便HAM们获得当日的预测情况

链接:https://prop.kc2g.com/renders/current/mufd-normal-now.svg
链接:https://prop.kc2g.com/renders/current/fof2-normal-now.svg

你可以从上面两种方法中任选一种来作为你的Bot将要获取的图像的链接

二、创建Bot

这一步将会十分简单,我会快速略过

首先登录你的Telegram账号并搜索@BotFather,然后输入”/newbot”来创建你的新的Bot,注意,在给你的Bot起Username的时候必须要以”bot”结尾,如”@IzumiChino_bot”

在创建完毕过后,BotFather会给你发送你的Bot的HTTP API,这个API就是你使用你的Bot的凭证,切记切记,不可外传,不可丢失!

准备好了吗,我们要开始写代码了

三、构建Bot代码

在我们一起就绪之后,那离我们的自动化Bot只差一步之遥——写程序,这样就可以让他开始为你服务,发送我们的每日传输预报

为了简单启事,我选用了Python来构建Bot的代码,原因就是Python的库用起来十分方便

构建Bot的代码我们将会用到三个库,分别是 “request”,”bs4″和”python-telegram-bot”

快速地,我们用pip install指令装好这几个需要的库

pip install request
pip install bs4
pip install python-telegram-bot==13.3

你会发现我再安装python-telegram-bot这个库的时候我指定13.3这个版本来安装,具体原因我会在后面说到。

当这些都已经准备好了的时候,你可以新建一个py文件来写代码了

一成不变的,我们先要导入所需要的库

import requests
from datetime import datetime, time, timedelta
from telegram import Bot
from telegram.ext import Updater, CommandHandler
from apscheduler.schedulers.background import BackgroundScheduler
from pytz import utc

其中的telegram和telegram.ext都是包含在python-telegram-bot库当中,代表我们需要从这个库的下属的telegram中引入Bot函数,从telegram.ext中引入Updater和CommandHandler函数

然后,我们进行全局变量的定义(相当于C/C++的const)

#这里填写你的Token
TOKEN = 'INPUT_YOUR_TOKEN_HERE'
#这里填写你希望获得的图片地址
URL = 'INPUT_YOUR_URL_HERE'

接下来我们就需要考虑如何去获取到你希望得到的预测图片,原先我们所使用的BeautifulSoup库中会存在返回图片失败的问题,故我们直接使用Request库来对图片进行获取

代码实现如下:

def get_image_url():
    response = requests.get(URL)
    if response.status_code == 200:
        return response.content
    return None

在下一个部分我们要考虑图和通过telegram把图片发送给用户

在这里,我们将会用到telegram.ext里面的update来实时获取用户uid

在写这个子函数之前,我们先定义一个bot,然后运用telegram的Bot函数给他定义

bot = Bot(token=TOKEN)

然后,我们就可以通过python-telegram-bot里所给的函数来将图片发送出去,当图片获取失败的时候会通过bot返回”Failed to get the image”给用户,代码实现如下:

def send_image_to_user(update, context):
    if cached_image_data:
        chat_id = update.effective_chat.id
        bot.send_photo(chat_id=chat_id, photo=cached_image_data, filename='image.jpg')
    else:
        context.bot.send_message(chat_id=update.effective_chat.id, text="Failed to get the image.")

最后的主程序部分,我们要实时获取用户的输入,一旦用户输入了”/start”发送给机器人,机器人就要立即发送图片给用户,这里我们将会用到CommandHandler函数来定义一个机器人函数的操作,也就是“/getocondition”命令代表着让机器人发送传输预报图象给用户,同时我还写了”/start”指令时bot的回复以及”/help“指令将会输出bot的指令列表给用户,代码实现如下:

def start(update, context):
    context.bot.send_message(chat_id=update.effective_chat.id, text="请通过 /getcondition 指令来获取当日传播预测图")

def helpcommand(update, context):
    context.bot.send_message(chat_id=update.effective_chat.id, text="Bot commands:\n/getcondition To get the image of condition\n/help To list commands of the bot\nAuthor:Mashiro Chino")

def main():
    fetch_image_data()  # 预先获取并缓存图片数据

    updater = Updater(TOKEN, use_context=True)
    dispatcher = updater.dispatcher

    start_handler = CommandHandler('start', start)
    get_condition_handler = CommandHandler('getcondition', send_image_to_user)
    help_handler = CommandHandler('help', helpcommand)

    dispatcher.add_handler(start_handler)
    dispatcher.add_handler(get_condition_handler)
    dispatcher.add_handler(help_handler)

    scheduler.add_job(fetch_image_data, 'cron', hour=0, minute=0, second=0)  # 每天UTC时间00:00运行任务
    scheduler.start()

    updater.start_polling()

注意这里的Updater函数,我们只传了一个参数TOKEN给他,在旧版本的python-telegram-bot库当中,这个函数只需要提供一个bot的TOKEN便可以使用,但是在最新版本中,这个函数被要求传递多个参数,使得代码实现更加麻烦(以下为新版定义)

classtelegram.ext.Updater(token: str = None, base_url: str = None, workers: int = 4, bot: telegram.bot.Bot = None, private_key: bytes = None, private_key_password: bytes = None, user_sig_handler: Callable = None, request_kwargs: Dict[str, Any] = None, persistence: BasePersistence = None, defaults: Defaults = None, use_context: bool = True, dispatcher: telegram.ext.dispatcher.Dispatcher = None, base_file_url: str = None)
Parameters:token (str, optional) – The bot’s token given by the @BotFather.
base_url (str, optional) – Base_url for the bot.
base_file_url (str, optional) – Base_file_url for the bot.
workers (int, optional) – Amount of threads in the thread pool for functions decorated with @run_async (ignored if dispatcher argument is used).
bot (telegram.Bot, optional) – A pre-initialized bot instance (ignored if dispatcher argument is used). If a pre-initialized bot is used, it is the user’s responsibility to create it using a Request instance with a large enough connection pool.
dispatcher (telegram.ext.Dispatcher, optional) – A pre-initialized dispatcher instance. If a pre-initialized dispatcher is used, it is the user’s responsibility to create it with proper arguments.
private_key (bytes, optional) – Private key for decryption of telegram passport data.
private_key_password (bytes, optional) – Password for above private key.
user_sig_handler (function, optional) – Takes signum, frame as positional arguments. This will be called when a signal is received, defaults are (SIGINT, SIGTERM, SIGABRT) settable with idle.
request_kwargs (dict, optional) – Keyword args to control the creation of a telegram.utils.request.Request object (ignored if bot or dispatcher argument is used). The request_kwargs are very useful for the advanced users who would like to control the default timeouts and/or control the proxy used for http communication.
use_context (bool, optional) – If set to True uses the context based callback API (ignored if dispatcher argument is used). Defaults to True
New users: set this to True.
persistence (telegram.ext.BasePersistence, optional) – The persistence class to store data that should be persistent over restarts (ignored if dispatcher argument is used).
defaults (telegram.ext.Defaults, optional) – An object containing default values to be used if not set explicitly in the bot methods.
新版参数解释

因此,相对于新版,旧版本的telegram.ext.Updater()函数更加简洁,容易上手,这就是我使用13.3版本的原因(也是我写这个程序卡了一晚上的原因)

在这段程序里,我添加了一个缓存避免在群组或者私聊里多个人同时发送”/getcondition”指令时会造成发送大量GET指令到hamqsl.com从而造成对他人服务器影响,同时也考虑到应该每日更新一次缓存,我添加了以下子程序

SEND_TIME = time(hour=0, minute=0, second=0)

scheduler = BackgroundScheduler(timezone=utc)

last_update_time = None

def fetch_image_data():
    global cached_image_data, last_update_time
    cached_image_data = get_image_url()
    last_update_time = datetime.utcnow()

好了,代码终于写完了,你可以尝试在你的服务器上运行试试啦,恭喜你获得了一个属于你自己的获取当日传播预测的Telegram Bot!

完整代码如下:

import requests
from datetime import datetime, time, timedelta
from telegram import Bot
from telegram.ext import Updater, CommandHandler
from apscheduler.schedulers.background import BackgroundScheduler
from pytz import utc

TOKEN = 'INPUT_YOUR_TOKEN_HERE'
URL = 'INPUT_YOUR_URL_HERE'
SEND_TIME = time(hour=0, minute=0, second=0)

bot = Bot(token=TOKEN)
scheduler = BackgroundScheduler(timezone=utc)

# 缓存的图片数据和最后更新时间
cached_image_data = None
last_update_time = None

def get_image_url():
    response = requests.get(URL)
    if response.status_code == 200:
        return response.content
    return None

def fetch_image_data():
    global cached_image_data, last_update_time
    cached_image_data = get_image_url()
    last_update_time = datetime.utcnow()

def send_image_to_user(update, context):
    if cached_image_data:
        chat_id = update.effective_chat.id
        bot.send_photo(chat_id=chat_id, photo=cached_image_data, filename='image.jpg')
    else:
        context.bot.send_message(chat_id=update.effective_chat.id, text="Failed to get the image.")

def start(update, context):
    context.bot.send_message(chat_id=update.effective_chat.id, text="请通过 /getcondition 指令来获取当日传播预测图")

def helpcommand(update, context):
    context.bot.send_message(chat_id=update.effective_chat.id, text="Bot commands:\n/getcondition To get the image of condition\n/help To list commands of the bot\nAuthor:Mashiro Chino")

def main():
    fetch_image_data()  # 预先获取并缓存图片数据

    updater = Updater(TOKEN, use_context=True)
    dispatcher = updater.dispatcher

    start_handler = CommandHandler('start', start)
    get_condition_handler = CommandHandler('getcondition', send_image_to_user)
    help_handler = CommandHandler('help', helpcommand)

    dispatcher.add_handler(start_handler)
    dispatcher.add_handler(get_condition_handler)
    dispatcher.add_handler(help_handler)

    scheduler.add_job(fetch_image_data, 'cron', hour=0, minute=0, second=0)  # 每天UTC时间00:00运行任务
    scheduler.start()

    updater.start_polling()

if __name__ == '__main__':
    main()

由于本文写作时间为凌晨四点至五点,本人还未睡觉,故行文匆忙,若有错误之处,还请麻烦各位指出

小花絮:这是本人跑完之后的结果,可以看到是因为timeout(

Traceback (most recent call last):
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connection.py", line 140, in _new_conn
    conn = connection.create_connection(
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\util\connection.py", line 83, in create_connection
    raise err
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\util\connection.py", line 73, in create_connection
    sock.connect(sa)
TimeoutError: timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 614, in urlopen
    httplib_response = self._make_request(conn, method, url,
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 360, in _make_request
    self._validate_conn(conn)
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 857, in _validate_conn
    super(HTTPSConnectionPool, self)._validate_conn(conn)
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 289, in _validate_conn
    conn.connect()
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connection.py", line 284, in connect
    conn = self._new_conn()
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connection.py", line 144, in _new_conn
    raise ConnectTimeoutError(
telegram.vendor.ptb_urllib3.urllib3.exceptions.ConnectTimeoutError: (<telegram.vendor.ptb_urllib3.urllib3.connection.VerifiedHTTPSConnection object at 0x000001B6470FA690>, 'Connection to api.telegram.org timed out. (connect timeout=5.0)')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\utils\request.py", line 252, in _request_wrapper
    resp = self._con_pool.request(*args, **kwargs)
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\request.py", line 68, in request
    return self.request_encode_body(method, url, fields=fields,
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\request.py", line 148, in request_encode_body
    return self.urlopen(method, url, **extra_kw)
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\poolmanager.py", line 244, in urlopen
    response = conn.urlopen(method, u.request_uri, **kw)
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 691, in urlopen
    return self.urlopen(method, url, body, headers, retries,
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 691, in urlopen
    return self.urlopen(method, url, body, headers, retries,
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 691, in urlopen
    return self.urlopen(method, url, body, headers, retries,
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\connectionpool.py", line 665, in urlopen
    retries = retries.increment(method, url, error=e, _pool=self,
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\vendor\ptb_urllib3\urllib3\util\retry.py", line 376, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
telegram.vendor.ptb_urllib3.urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.telegram.org', port=443): Max retries exceeded with url: /botTOKEN/getMe (Caused by ConnectTimeoutError(<telegram.vendor.ptb_urllib3.urllib3.connection.VerifiedHTTPSConnection object at 0x000001B6470FA690>, 'Connection to api.telegram.org timed out. (connect timeout=5.0)'))

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:/Users/Mashiro Chino/Desktop/Bot.py", line 33, in <module>
    main()
  File "C:/Users/Mashiro Chino/Desktop/Bot.py", line 30, in main
    updater.start_polling()
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\ext\updater.py", line 285, in start_polling
    self._init_thread(self.dispatcher.start, "dispatcher", ready=dispatcher_ready)
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\ext\updater.py", line 225, in _init_thread
    name=f"Bot:{self.bot.id}:{name}",
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\bot.py", line 330, in id
    return self.bot.id
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\bot.py", line 323, in bot
    self._bot = self.get_me()
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\bot.py", line 126, in decorator
    result = func(*args, **kwargs)
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\bot.py", line 407, in get_me
    result = self._post('getMe', timeout=timeout, api_kwargs=api_kwargs)
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\bot.py", line 258, in _post
    return self.request.post(
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\utils\request.py", line 349, in post
    result = self._request_wrapper(
  File "C:\Users\Mashiro Chino\AppData\Local\Programs\Python\Python311\Lib\site-packages\telegram\utils\request.py", line 258, in _request_wrapper
    raise NetworkError(f'urllib3 HTTPError {error}') from error
telegram.error.NetworkError: urllib3 HTTPError HTTPSConnectionPool(host='api.telegram.org', port=443): Max retries exceeded with url: /botTOKEN/getMe (Caused by ConnectTimeoutError(<telegram.vendor.ptb_urllib3.urllib3.connection.VerifiedHTTPSConnection object at 0x000001B6470FA690>, 'Connection to api.telegram.org timed out. (connect timeout=5.0)'))

睡觉去了,73,再会!

致谢:

传播预测图的获取感谢Neo_Chen(BU4AK)提供的数据并为本人讲解其数据作用!

代码部分感谢huige和acolaen帮助本人纠错、修改代码!

评论

  1. 头像
    Shiro
    Android Chrome 116.0.0.0
    4月前
    2023-8-20 21:43:11

    机器人很好用!尤其是雌小鬼功能~

    • 头像
      博主
      Shiro
      Windows Firefox 116.0
      3月前
      2023-8-27 18:33:25

      贴贴老婆!喵呜喵!

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇