diff --git a/setup.py b/setup.py index 35927e35..8e2c30b3 100755 --- a/setup.py +++ b/setup.py @@ -46,6 +46,9 @@ ERRORS_OUT = LIBRARY_DIR / 'errors/rpcerrorlist.py' METHODS_IN = GENERATOR_DIR / 'data/methods.csv' +# Which raw API methods are covered by *friendly* methods in the client? +FRIENDLY_IN = GENERATOR_DIR / 'data/friendly.csv' + TLOBJECT_IN_TLS = [Path(x) for x in GENERATOR_DIR.glob('data/*.tl')] TLOBJECT_OUT = LIBRARY_DIR / 'tl' IMPORT_DEPTH = 2 @@ -63,7 +66,7 @@ def generate(which, action='gen'): layer = next(filter(None, map(find_layer, TLOBJECT_IN_TLS))) errors = list(parse_errors(ERRORS_IN)) - methods = list(parse_methods(METHODS_IN, {e.str_code: e for e in errors})) + methods = list(parse_methods(METHODS_IN, FRIENDLY_IN, {e.str_code: e for e in errors})) tlobjects = list(itertools.chain(*( parse_tl(file, layer, methods) for file in TLOBJECT_IN_TLS))) diff --git a/telethon/client/auth.py b/telethon/client/auth.py index 3428c004..38053781 100644 --- a/telethon/client/auth.py +++ b/telethon/client/auth.py @@ -271,6 +271,10 @@ class AuthMethods(MessageParseMethods, UserMethods): This method will send the code if it's not provided. + .. note:: + + In most cases, you should simply use `start()` and not this method. + Arguments phone (`str` | `int`): The phone to send the code to if no code was provided, diff --git a/telethon_generator/data/friendly.csv b/telethon_generator/data/friendly.csv new file mode 100644 index 00000000..eef85540 --- /dev/null +++ b/telethon_generator/data/friendly.csv @@ -0,0 +1,25 @@ +ns,friendly,raw +account.AccountMethods,takeout,invokeWithTakeout account.initTakeoutSession account.finishTakeoutSession +auth.AuthMethods,sign_in,auth.signIn auth.importBotAuthorization +auth.AuthMethods,sign_up,auth.signUp +auth.AuthMethods,send_code_request,auth.sendCode auth.resendCode +auth.AuthMethods,log_out,auth.logOut +auth.AuthMethods,edit_2fa,account.updatePasswordSettings +bots.BotMethods,inline_query,messages.getInlineBotResults +chats.ChatMethods,action,messages.setTyping +chats.ChatMethods,iter_participants,channels.getParticipants +chats.ChatMethods,iter_admin_log,channels.getAdminLog +dialogs.DialogMethods,iter_dialogs,messages.getDialogs +dialogs.DialogMethods,iter_drafts,messages.getAllDrafts +dialogs.DialogMethods,edit_folder,folders.deleteFolder folders.editPeerFolders +downloads.DownloadMethods,download_media,upload.getFile +messages.MessageMethods,iter_messages,messages.searchGlobal messages.search messages.getHistory channels.getMessages messages.getMessages +messages.MessageMethods,send_message,messages.sendMessage +messages.MessageMethods,forward_messages,messages.forwardMessages +messages.MessageMethods,edit_message,messages.editInlineBotMessage messages.editMessage +messages.MessageMethods,delete_messages,channels.deleteMessages messages.deleteMessages +messages.MessageMethods,send_read_acknowledge,messages.readMentions channels.readHistory messages.readHistory +updates.UpdateMethods,catch_up,updates.getDifference updates.getChannelDifference +uploads.UploadMethods,send_file,messages.sendMedia messages.sendMultiMedia messages.uploadMedia +uploads.UploadMethods,upload_file,upload.saveFilePart upload.saveBigFilePart +users.UserMethods,get_entity,users.getUsers messages.getChats channels.getChannels contacts.resolveUsername diff --git a/telethon_generator/data/methods.csv b/telethon_generator/data/methods.csv index f43967f9..49f399e4 100644 --- a/telethon_generator/data/methods.csv +++ b/telethon_generator/data/methods.csv @@ -58,6 +58,7 @@ auth.dropTempAuthKeys,both, auth.exportAuthorization,both,DC_ID_INVALID auth.importAuthorization,both,AUTH_BYTES_INVALID USER_ID_INVALID auth.importBotAuthorization,both,ACCESS_TOKEN_EXPIRED ACCESS_TOKEN_INVALID API_ID_INVALID +auth.logOut,both, auth.recoverPassword,user,CODE_EMPTY auth.requestPasswordRecovery,user,PASSWORD_EMPTY auth.resendCode,user,PHONE_NUMBER_INVALID diff --git a/telethon_generator/generators/docs.py b/telethon_generator/generators/docs.py index 351ca496..89554f4a 100755 --- a/telethon_generator/generators/docs.py +++ b/telethon_generator/generators/docs.py @@ -380,6 +380,24 @@ def _write_html_pages(root, tlobjects, methods, layer, input_res): 'telethon.errors.') docs.write_title('Example', id='examples') + if tlobject.friendly: + ns, friendly = tlobject.friendly + docs.write_text( + 'Please refer to the documentation of client.{1}() ' + 'to learn about the parameters and see several code ' + 'examples on how to use it.' + .format(ns, friendly) + ) + docs.write_text( + 'The method above is the recommended way to do it. ' + 'If you need more control over the parameters or want ' + 'to learn how it is implemented, open the details by ' + 'clicking on the "Details" text.' + ) + docs.write('
') + docs.write('''
\
 from telethon.sync import TelegramClient
 from telethon import functions, types
@@ -399,6 +417,8 @@ def _write_html_pages(root, tlobjects, methods, layer, input_res):
                         docs.write('.stringify()')
 
                 docs.write(')
') + if tlobject.friendly: + docs.write('
') depth = '../' * (2 if tlobject.namespace else 1) docs.add_script(src='prependPath = "{}";'.format(depth)) diff --git a/telethon_generator/parsers/methods.py b/telethon_generator/parsers/methods.py index 7911c07c..ebc7e22f 100644 --- a/telethon_generator/parsers/methods.py +++ b/telethon_generator/parsers/methods.py @@ -1,5 +1,6 @@ import csv import enum +import warnings class Usability(enum.Enum): @@ -10,9 +11,10 @@ class Usability(enum.Enum): class MethodInfo: - def __init__(self, name, usability, errors): + def __init__(self, name, usability, errors, friendly): self.name = name self.errors = errors + self.friendly = friendly try: self.usability = { 'unknown': Usability.UNKNOWN, @@ -25,11 +27,19 @@ class MethodInfo: 'unknown, not {}'.format(usability)) from None -def parse_methods(csv_file, errors_dict): +def parse_methods(csv_file, friendly_csv_file, errors_dict): """ Parses the input CSV file with columns (method, usability, errors) and yields `MethodInfo` instances as a result. """ + raw_to_friendly = {} + with friendly_csv_file.open(newline='') as f: + f = csv.reader(f) + next(f, None) # header + for ns, friendly, raw_list in f: + for raw in raw_list.split(): + raw_to_friendly[raw] = (ns, friendly) + with csv_file.open(newline='') as f: f = csv.reader(f) next(f, None) # header @@ -40,4 +50,9 @@ def parse_methods(csv_file, errors_dict): raise ValueError('Method {} references unknown errors {}' .format(method, errors)) from None - yield MethodInfo(method, usability, errors) + friendly = raw_to_friendly.pop(method, None) + yield MethodInfo(method, usability, errors, friendly) + + if raw_to_friendly: + warnings.warn('note: unknown raw methods in friendly mapping: {}' + .format(', '.join(raw_to_friendly))) diff --git a/telethon_generator/parsers/tlobject/parser.py b/telethon_generator/parsers/tlobject/parser.py index a502f623..5aa0fc9a 100644 --- a/telethon_generator/parsers/tlobject/parser.py +++ b/telethon_generator/parsers/tlobject/parser.py @@ -58,10 +58,13 @@ def _from_line(line, is_function, method_info, layer): ) name = match.group(1) - if name in method_info: - usability = method_info[name].usability + method_info = method_info.get(name) + if method_info: + usability = method_info.usability + friendly = method_info.friendly else: usability = Usability.UNKNOWN + friendly = None return TLObject( fullname=name, @@ -70,6 +73,7 @@ def _from_line(line, is_function, method_info, layer): is_function=is_function, layer=layer, usability=usability, + friendly=friendly, args=[TLArg(name, arg_type, brace != '') for brace, name, arg_type in args_match] ) diff --git a/telethon_generator/parsers/tlobject/tlobject.py b/telethon_generator/parsers/tlobject/tlobject.py index 616e28af..95ce6e42 100644 --- a/telethon_generator/parsers/tlobject/tlobject.py +++ b/telethon_generator/parsers/tlobject/tlobject.py @@ -14,7 +14,7 @@ WHITELISTED_MISMATCHING_IDS = { class TLObject: def __init__(self, fullname, object_id, args, result, - is_function, usability, layer): + is_function, usability, friendly, layer): """ Initializes a new TLObject, given its properties. @@ -25,6 +25,7 @@ class TLObject: :param result: The result type of the TL object :param is_function: Is the object a function or a type? :param usability: The usability for this method. + :param friendly: A tuple (namespace, friendly method name) if known. :param layer: The layer this TLObject belongs to. """ # The name can or not have a namespace @@ -38,6 +39,7 @@ class TLObject: self.result = result self.is_function = is_function self.usability = usability + self.friendly = friendly self.id = None if object_id is None: self.id = self.infer_id()