Skip to content

Commit aa1074f

Browse files
author
Koehler, Jonathan
committed
osm_edit dialog for gpx upload
1 parent f385aa0 commit aa1074f

File tree

6 files changed

+181
-58
lines changed

6 files changed

+181
-58
lines changed

bot.py

+22-11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import ee_osmose
55
import osmose
66
from telegram import *
7+
import telegram.error
78
from telegram.ext import (Updater, CommandHandler, MessageHandler, Filters,
89
CallbackQueryHandler, CallbackContext)
910

@@ -62,7 +63,7 @@ def user_issue(update: Update, context: CallbackContext):
6263

6364
def send_issue(bot: Bot, chat_id: str, issue: osmose.Issue):
6465
keyboard = InlineKeyboardMarkup([[InlineKeyboardButton('Location', callback_data=issue.id),
65-
InlineKeyboardButton('Welt', callback_data=5)]])
66+
InlineKeyboardButton('Welt', callback_data='edit')]])
6667

6768
bot.send_message(chat_id, issue.__str__(), reply_markup=keyboard)
6869

@@ -111,7 +112,7 @@ def more_iss(query: CallbackQuery, context: CallbackContext):
111112
context.user_data['det_iss'] = iss
112113
del context.user_data['list']
113114
keyboard = InlineKeyboardMarkup([[InlineKeyboardButton('Location', callback_data='loc'),
114-
InlineKeyboardButton('Description', url=iss.desc_url())]])
115+
InlineKeyboardButton('Description', url=iss.desc_url())], [InlineKeyboardButton('Edit', callback_data='edit')]])
115116
query.edit_message_text(str(iss), reply_markup=keyboard, parse_mode=ParseMode.HTML)
116117

117118

@@ -129,13 +130,19 @@ def button(update: Update, context):
129130

130131
if query.data == 'next':
131132
next_iss(query, context)
133+
query.answer()
132134
elif query.data == 'prev':
133135
prev_iss(query, context)
136+
query.answer()
134137
elif query.data == 'loc':
135138
iss_loc(query, context)
139+
query.answer()
140+
elif query.data.startswith('edit'):
141+
return
136142
else:
137143
more_iss(query, context)
138-
query.answer()
144+
query.answer()
145+
139146
print(query.data)
140147

141148

@@ -159,21 +166,25 @@ def main():
159166
editor = bot_osm_edit.ElemEditor()
160167
# on different commands - answer in Telegram
161168
dp.add_handler(CommandHandler("start", start))
162-
dp.add_handler(CommandHandler("help", help))
163-
dp.add_handler(CommandHandler('user', user_issue))
164-
dp.add_handler(CallbackQueryHandler(button))
165-
dp.add_handler(MessageHandler(Filters.location, loc_issue))
166-
dp.add_handler(CommandHandler("loc", loc_issue))
167-
dp.add_handler(editor.get_conversation())
169+
dp.add_handler(CommandHandler("help", help), 1)
170+
dp.add_handler(CommandHandler('user', user_issue), 1)
171+
dp.add_handler(CallbackQueryHandler(button), 1)
172+
dp.add_handler(MessageHandler(Filters.location, loc_issue), 1)
173+
dp.add_handler(CommandHandler("loc", loc_issue), 1)
174+
dp.add_handler(editor.get_conversation(), 0)
168175

169176
# on non-command i.e message - echo the message on Telegram
170177
# dp.add_handler(MessageHandler(Filters.text, echo))
171178

172179
# log all errors
173180
dp.add_error_handler(error)
174181

175-
# Start the Bot
176-
updater.start_polling()
182+
try:
183+
# Start the Bot
184+
updater.start_polling()
185+
except telegram.error.NetworkError:
186+
logger.error('could not connect to Telegram Server')
187+
177188

178189
# Run the bot until you press Ctrl-C or the process receives SIGINT,
179190
# SIGTERM or SIGABRT. This should be used most of the time, since

bot_osm_edit.py

+94-13
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,122 @@
1-
from telegram.ext import ConversationHandler, CommandHandler, MessageHandler, Filters, CallbackContext
2-
from telegram import Update, CallbackQuery
1+
from telegram.ext import ConversationHandler, CommandHandler, MessageHandler, Filters, CallbackContext, CallbackQueryHandler, DispatcherHandlerStop
2+
from telegram import Update, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
3+
import osm.osm_util
4+
import osm.osm_api
35
import logging
6+
import io
47

58
# Enable logging
69
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
710
level=logging.INFO)
811

912
logger = logging.getLogger(__name__)
1013

11-
CHOOSING, TYPING_CHOICE, TYPING_REPLY = range(3)
14+
CHOOSING, TAG_CHOICE, VALUE_REPLY, TYPING_REPLY, LOCATION, TEXT, DESCRIPTION, NAME, GPX_SAVE, SAVE = range(10)
1215

1316

1417
class ElemEditor:
1518
def __init__(self):
19+
self.osmapi = osm.osm_api.OsmApi()
1620
pass
1721

1822
def get_conversation(self):
1923
return ConversationHandler(
20-
entry_points=[CommandHandler('_edit', self.start)],
24+
entry_points=[CallbackQueryHandler(self.start),
25+
MessageHandler(Filters.document, self.gpx_up)],
2126

2227
states={
2328
CHOOSING: [MessageHandler(Filters.regex('tag'), self.tag),
2429
MessageHandler(Filters.regex('cancel'), self.cancel)
2530
],
2631

27-
TYPING_CHOICE: [MessageHandler(Filters.text, self.value)
28-
],
2932

30-
TYPING_REPLY: [MessageHandler(Filters.text, self.edit_info),
33+
TAG_CHOICE: [MessageHandler(Filters.text, self.tag)],
34+
35+
TYPING_REPLY: [MessageHandler(Filters.text, self.value),
36+
MessageHandler(Filters.location, self.location)
3137
],
38+
NAME: [MessageHandler(Filters.text, self.gpx_name)],
39+
40+
DESCRIPTION: [CommandHandler('skip', self.gpx_up_content),
41+
MessageHandler(Filters.text, self.gpx_desc)],
42+
43+
GPX_SAVE:[CommandHandler('save', self.gpx_up_content),
44+
CallbackQueryHandler(self.gpx_toggles, 0)
45+
]
3246
},
3347

34-
fallbacks=[MessageHandler(Filters.regex('^Done$'), self.cancel)]
48+
fallbacks=[MessageHandler(Filters.regex('^Done$'), self.cancel),
49+
MessageHandler(Filters.command, self.invalid, 0),
50+
CallbackQueryHandler(self.invalid)]
3551
)
3652

37-
def start(self, update, context):
38-
print('hello here conversation start')
39-
return CHOOSING
53+
def start(self, update: Update, context: CallbackContext):
54+
if update.callback_query.data == 'edit':
55+
update.callback_query.answer('enter edit conversation')
56+
try:
57+
thing = context.user_data['edit']
58+
# send message containing all tags and values of object
59+
return TAG_CHOICE
60+
except KeyError:
61+
context.bot.send_message(update.effective_chat.id, 'select action') # for now only Note create
62+
context.user_data['subject'] = osm.osm_util.Note
63+
context.bot.send_message(update.effective_chat.id, 'please send location.')
64+
return TYPING_REPLY
65+
return # handled by bot
66+
67+
def gpx_up(self, update: Update, context):
68+
data = open(update.effective_message.document.get_file().download()).read()
69+
context.user_data['gpx'] = osm.osm_util.Trace(None, data, None, None, None)
70+
update.message.reply_text('please send trace-name.')
71+
return NAME
72+
73+
def gpx_name(self, update, context):
74+
name = update.message.text
75+
context.user_data['gpx'].name = name
76+
update.message.reply_text('please write a Description, or use /skip .')
77+
return DESCRIPTION
78+
79+
def gpx_desc(self, update, context):
80+
context.user_data['gpx'].desc = update.message.text
81+
return GPX_SAVE
82+
83+
def gpx_up_content(self, update, context):
84+
gpx: osm.osm_util.Trace = context.user_data['gpx']
85+
markup = InlineKeyboardMarkup([[InlineKeyboardButton(gpx.visibility, callback_data='vis')],
86+
[InlineKeyboardButton('Upload', callback_data='save')]])
87+
context.bot.send_message(update.effective_chat.id, str(gpx), reply_markup=markup)
88+
return GPX_SAVE
89+
90+
def gpx_toggles(self, update, context):
91+
gpx = context.user_data['gpx']
92+
if update.callback_query.data == 'save':
93+
self.gpx_save(update, context)
94+
del context.user_data['gpx']
95+
self.cancel(update, context)
96+
elif update.callback_query.data == 'public':
97+
gpx.public = not gpx.public
98+
context.user_data['gpx'] = gpx
99+
elif update.callback_query.data == 'vis':
100+
vis = ['identifiable', 'trackable', 'public', 'private']
101+
gpx.visibility = vis[vis.index(gpx.visibility) - 1]
102+
context.user_data['gpx'] = gpx
103+
self.gpx_up_content(update, context)
104+
105+
def gpx_save(self, update, context):
106+
gpx = context.user_data['gpx']
107+
tid = self.osmapi.upload_gpx(gpx.gpx, gpx.name, gpx.desc, gpx.tags, gpx.public, gpx.visibility)
108+
context.bot.send_message(update.effective_chat.id, str(tid))
109+
110+
def invalid(self, update, context):
111+
logger.error('invalid command')
112+
113+
def location(self, update, context):
114+
loc = update.message.location
115+
update.message.reply_text('send Note text')
116+
return TYPING_REPLY
40117

41118
def tag(self, update, context):
42-
print('hay here is converseation Tag')
119+
print('hay here is conversation Tag')
43120
return CHOOSING
44121

45122
def value(self):
@@ -51,5 +128,9 @@ def edit_info(self, update: Update, context: CallbackContext):
51128
update.callback_query.edit_message_text()
52129
return CHOOSING
53130

54-
def cancel(self):
131+
def note(self):
55132
pass
133+
134+
def cancel(self, update, context):
135+
update.callback_query.answer('exit edit conversation')
136+
return ConversationHandler.END

osm/a_osm_api.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,11 @@ def get_full_element(self, etype: str, eid: int) -> list:
235235
GET /api/0.6/[way|relation]/#id/full
236236
"""
237237

238-
# reduction purposefully left out
238+
# reduction purposefully left out (only for moderators)
239239

240240
''' GPX '''
241241

242-
def get_bbox_gpx(self, bbox: tuple, page: int) -> str:
242+
def get_bbox_gpx(self, bbox: tuple, page: int) -> dict:
243243
"""
244244
returns 5000GPS trackpoints max, increase page for any additional 5000
245245
@@ -254,7 +254,7 @@ def upload_gpx(self, trace: str, name: str, description: str, tags: set,
254254
"""
255255
uploads gpx trace
256256
257-
:param trace: gpx trace file location
257+
:param trace: gpx trace file string
258258
:param description: gpx description
259259
:param name: file name on osm
260260
:param tags: additional tags mappingtour, etc
@@ -271,7 +271,7 @@ def update_gpx(self, tid: int, trace: str, description: str, tags: set,
271271
updates gpx trace
272272
273273
:param tid: uploaded trace id
274-
:param trace: gpx trace file location
274+
:param trace: gpx trace as string
275275
:param description: gpx description
276276
:param tags: additional tags mappingtour, etc
277277
:param public: True for public tracks else False
@@ -291,15 +291,16 @@ def get_meta_gpx(self, gpx_id: int) -> dict:
291291
"""
292292
GET /api/0.6/gpx/#id/details
293293
294-
:param gpx_id: id identifying the gpx file on the server
294+
:param gpx_id: id identifying the gpx file as string
295295
:returns: dictionary representing the metadata
296296
"""
297297
raise NotImplementedError
298298

299299
def get_gpx(self, gpx_id: int) -> str:
300300
"""
301+
301302
:param gpx_id: id identifying the gpx file on the server
302-
:returns: string file location
303+
:returns: gpx file as string
303304
"""
304305
raise NotImplementedError
305306

osm/osm_api.py

+15-12
Original file line numberDiff line numberDiff line change
@@ -370,14 +370,14 @@ def get_element_bbox(self, bbox: tuple) -> list:
370370

371371
''' GPX '''
372372

373-
def get_bbox_gpx(self, bbox: tuple, page: int = 0) -> str:
373+
def get_bbox_gpx(self, bbox: tuple, page: int = 0) -> list:
374374
"""
375375
returns 5000GPS trackpoints max, increase page for any additional 5000
376376
GET /api/0.6/trackpoints?bbox=left,bottom,right,top&page=pageNumber
377377
"""
378378
data = requests.get(self.base_url + '/trackpoints?bbox={}' + ','.join(map(str, bbox)), auth=(NAME, PASS))
379379
if data.ok:
380-
return data.text
380+
return self.__parse_gpx_info(data.text)
381381
raise Exception(data.text)
382382

383383
def upload_gpx(self, trace: str, name: str, description: str, tags: set,
@@ -386,7 +386,7 @@ def upload_gpx(self, trace: str, name: str, description: str, tags: set,
386386
uploads gpx trace
387387
POST /api/0.6/gpx/create
388388
"""
389-
content = {'description': description, 'tags': ','.join(tags), 'public': public, 'visibility': visibility}
389+
content = {'description': description, 'tags': ','.join(tags), 'visibility': visibility}
390390
req_file = {'file': (name, trace)}
391391
data = requests.post(self.base_url + '/gpx/create', auth=(NAME, PASS), files=req_file, data=content)
392392
if data.ok:
@@ -434,17 +434,20 @@ def get_own_gpx(self) -> list:
434434
"""
435435
data = requests.get(self.base_url + '/user/gpx_files', auth=(NAME, PASS))
436436
if data.ok:
437-
tree = ElemTree.fromstring(data.text)
438-
lst = []
439-
for item in tree.findall('gpx_file'):
440-
attrib = item.attrib
441-
attrib['timestamp'] = dateutil.parser.isoparse(attrib['timestamp'])
442-
for info in item:
443-
attrib[info.tag] = info.text
444-
lst.append(attrib)
445-
return lst
437+
return self.__parse_gpx_info(data.text)
446438
raise Exception(data.text)
447439

440+
def __parse_gpx_info(self, xml):
441+
tree = ElemTree.fromstring(xml)
442+
lst = []
443+
for item in tree.findall('gpx_file'):
444+
attrib = item.attrib
445+
attrib['timestamp'] = str(dateutil.parser.isoparse(attrib['timestamp']))
446+
for info in item:
447+
attrib[info.tag] = info.text
448+
lst.append(attrib)
449+
return lst
450+
448451
''' user '''
449452

450453
def get_user(self, uid: int) -> dict:

0 commit comments

Comments
 (0)