-
Notifications
You must be signed in to change notification settings - Fork 12
/
line_bot.py
208 lines (180 loc) · 9.32 KB
/
line_bot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
"""This python file will handle line webhooks."""
import json
from threading import Thread
import zmq
from discord import SyncWebhook, File
from flask import Flask, request, abort
from flask.logging import create_logger
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, ImageMessage, VideoMessage, VideoSendMessage, \
TextSendMessage, AudioMessage, AudioSendMessage
import line_notify
import utilities as utils
config = utils.read_config()
line_bot_api = LineBotApi(config['line_channel_access_token'])
handler = WebhookHandler(config['line_channel_secret'])
app = Flask(__name__)
log = create_logger(app)
context = zmq.Context()
socket = context.socket(zmq.SUB)
socket.connect("tcp://localhost:5555")
socket.setsockopt_string(zmq.SUBSCRIBE, '')
@app.route("/callback", methods=['POST'])
def callback():
"""Callback function for line webhook."""
# get X-Line-Signature header value
signature = request.headers['X-Line-Signature']
# get request body as text
body = request.get_data(as_text=True)
log.info("Request body: %s", body)
# handle webhook body
try:
handler.handle(body, signature)
except InvalidSignatureError:
print("Invalid signature. Please check your channel access token/channel secret.")
abort(400)
return 'OK'
@app.route("/notify", methods=['POST'])
def notify():
body = request.get_data(as_text=True)
log.info("Request body: %s", body)
auth_code = request.form.get('code')
group_id = request.form.get('state').split('_')[0]
group_name = request.form.get('state').split('_')[1]
notify_token = line_notify.get_notify_token_by_auth_code(auth_code)
binding_code = utils.generate_binding_code(group_id, group_name, notify_token)
push_message = f"\nLine Notify綁定成功!\n" \
f"請至欲同步的Discord頻道中\n" \
f"\n----------------------\n" \
f"輸入以下指令來完成綁定\n" \
f"/link {binding_code}\n" \
f"----------------------\n" \
f"\n※注意※\n" \
f"此綁定碼僅能使用一次\n" \
f"並將於5分鐘後過期"
line_notify.send_message(push_message, notify_token)
show_message = f"Successfully connected to LINE Notify!\n" \
f"You may now close this page."
return show_message
@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
"""Handle message event."""
if event.source.type == 'user':
return
if event.source.type == 'group':
message_received = event.message.text
user_id = event.source.user_id
group_id = event.source.group_id
reply_token = event.reply_token
subscribed_line_channels = utils.get_subscribed_line_channels()
if message_received == '!ID':
line_bot_api.reply_message(reply_token, TextSendMessage(text=group_id))
elif message_received == '!綁定':
if group_id in subscribed_line_channels:
reply_message = "此群組已綁定"
else:
group_name = line_bot_api.get_group_summary(group_id).group_name
line_notify_state = group_id + '_' + group_name
auth_link = line_notify.create_auth_link(line_notify_state)
reply_message = f"請先點擊下方連結進行Line Notify綁定!\n" \
f"並在頁面中選擇此群組後, 點擊「同意並連動」\n" \
f"完成綁定後, 系統將傳送一組Discord配對碼至此群組\n" \
f"\n{auth_link}"
line_bot_api.reply_message(reply_token, TextSendMessage(text=reply_message))
elif group_id in subscribed_line_channels:
subscribed_info = utils.get_subscribed_info_by_line_group_id(group_id)
author = line_bot_api.get_group_member_profile(group_id, user_id).display_name
author_image = line_bot_api.get_group_member_profile(group_id, user_id).picture_url
discord_webhook = SyncWebhook.from_url(subscribed_info['discord_channel_webhook'])
discord_webhook.send(message_received, username=f"{author} - (Line訊息)",
avatar_url=author_image)
@handler.add(MessageEvent, message=ImageMessage)
def handle_image(event):
"""Handle image message event."""
if event.source.type == 'user':
return
if event.source.type == 'group':
user_id = event.source.user_id
group_id = event.source.group_id
subscribed_line_channels = utils.get_subscribed_line_channels()
if group_id in subscribed_line_channels:
subscribed_info = utils.get_subscribed_info_by_line_group_id(group_id)
author = line_bot_api.get_group_member_profile(group_id, user_id).display_name
author_image = line_bot_api.get_group_member_profile(group_id, user_id).picture_url
source = line_bot_api.get_message_content(event.message.id)
file_path = utils.download_file_from_line(subscribed_info['folder_name'], source,
event.message.type)
discord_webhook = SyncWebhook.from_url(subscribed_info['discord_channel_webhook'])
discord_webhook.send(file=File(file_path), username=f"{author} - (Line訊息)",
avatar_url=author_image)
@handler.add(MessageEvent, message=VideoMessage)
def handle_video(event):
"""Handle video message event."""
if event.source.type == 'user':
return
if event.source.type == 'group':
user_id = event.source.user_id
group_id = event.source.group_id
subscribed_line_channels = utils.get_subscribed_line_channels()
if group_id in subscribed_line_channels:
subscribed_info = utils.get_subscribed_info_by_line_group_id(group_id)
author = line_bot_api.get_group_member_profile(group_id, user_id).display_name
author_image = line_bot_api.get_group_member_profile(group_id, user_id).picture_url
source = line_bot_api.get_message_content(event.message.id)
file_path = utils.download_file_from_line(subscribed_info['folder_name'], source,
event.message.type)
discord_webhook = SyncWebhook.from_url(subscribed_info['discord_channel_webhook'])
discord_webhook.send(file=File(file_path), username=f"{author} - (Line訊息)",
avatar_url=author_image)
@handler.add(MessageEvent, message=AudioMessage)
def handle_audio(event):
"""Handle audio message event."""
if event.source.type == 'user':
return
if event.source.type == 'group':
user_id = event.source.user_id
group_id = event.source.group_id
subscribed_line_channels = utils.get_subscribed_line_channels()
if group_id in subscribed_line_channels:
subscribed_info = utils.get_subscribed_info_by_line_group_id(group_id)
author = line_bot_api.get_group_member_profile(group_id, user_id).display_name
author_image = line_bot_api.get_group_member_profile(group_id, user_id).picture_url
source = line_bot_api.get_message_content(event.message.id)
file_path = utils.download_file_from_line(subscribed_info['folder_name'], source,
event.message.type)
discord_webhook = SyncWebhook.from_url(subscribed_info['discord_channel_webhook'])
discord_webhook.send(file=File(file_path), username=f"{author} - (Line訊息)",
avatar_url=author_image)
def receive_from_discord():
"""Receive from discord bot."""
while True:
received = socket.recv_json()
received = json.loads(received)
subscribed_info = utils.get_subscribed_info_by_sub_num(received['sub_num'])
group_id = subscribed_info['line_group_id']
message = received['message']
if received['msg_type'] == 'video':
if message == "":
message = f"{received['author']}: 傳送了影片"
else:
message = f"{received['author']}: {message}(影片)"
line_notify.send_message(message, subscribed_info['line_notify_token'])
line_bot_api.push_message(group_id,
VideoSendMessage(
original_content_url=received['video_url'],
preview_image_url=received['thumbnail_url']))
if received['msg_type'] == 'audio':
if message == "":
message = f"{received['author']}: 傳送了音訊"
else:
message = f"{received['author']}: {message}(音訊)"
line_notify.send_message(message, subscribed_info['line_notify_token'])
line_bot_api.push_message(group_id,
AudioSendMessage(
original_content_url=received['audio_url'],
duration=received['audio_duration']))
thread = Thread(target=receive_from_discord)
thread.start()
if __name__ == "__main__":
app.run()