southbridgeio / tdlib-ruby

Ruby bindings and client for TDLib
MIT License
95 stars 48 forks source link

The README.md example doesn't work #63

Open yart opened 1 year ago

yart commented 1 year ago

My Gemfile:

gem 'dry-configurable', '0.15.0'
gem 'tdlib-ruby'

Trying to run the example from the current README and getting only the following:

/home/yart/work/alcom/coding/tapp/vendor/bundle/ruby/3.2.0/gems/dry-configurable-0.15.0/lib/dry/configurable/dsl.rb:28:in `initialize' [dry-configurable] passing a constructor as a block is deprecated and will be removed in the next major version
Provide a `constructor:` keyword argument instead

/home/yart/work/alcom/coding/tapp/vendor/bundle/ruby/3.2.0/gems/dry-configurable-0.15.0/lib/dry/configurable/dsl.rb:28:in `initialize' [dry-configurable] default value as positional argument to settings is deprecated and will be removed in the nex
t major version
Provide a `default:` keyword argument instead

/home/yart/work/alcom/coding/tapp/vendor/bundle/ruby/3.2.0/gems/dry-configurable-0.15.0/lib/dry/configurable/dsl.rb:28:in `initialize' [dry-configurable] default value as positional argument to settings is deprecated and will be removed in the nex
t major version
Provide a `default:` keyword argument instead

I've been tried ruby 2.7.8 and 3.2.2 — the same result.

The last warning has been repeated several times. And that's all this code does.

I've changed the dry-configurable version according to this issue: https://github.com/southbridgeio/tdlib-ruby/issues/62. I had the same error before.

Who can help me, guys?

yart commented 1 year ago

Changed this part of tdlib-ruby.rb in such a way:

  setting(:client) do
    setting(:api_id) { |val| val.to_i } # before: setting :api_id, &:to_i
    setting :api_hash
    setting :use_test_dc, default: false # before: setting :use_test_dc, false
    setting :database_directory, default: "#{Dir.home}/.tdlib-ruby/db" # before: setting :database_directory, "#{Dir.home}/.tdlib-ruby/db"
    setting :files_directory, default: "#{Dir.home}/.tdlib-ruby/data" # before: setting :files_directory, "#{Dir.home}/.tdlib-ruby/data"
    setting :use_file_database, default: true # before: setting :use_file_database, true
    setting :use_chat_info_database, default: true # before: setting :use_chat_info_database, true
    setting :use_secret_chats, default: true # before: setting :use_secret_chats, true
    setting :use_message_database, default: true # before: setting :use_message_database, true
    setting :system_language_code, default: 'en' # before: setting :system_language_code, 'en'
    setting :device_model, default: 'Ruby TD client' # before: setting :device_model, 'Ruby TD client'
    setting :system_version, default: 'Unknown' # before: setting :system_version, 'Unknown'
    setting :application_version, default: '1.0' # before: setting :application_version, '1.0'
    setting :enable_storage_optimizer, default: true # before: setting :enable_storage_optimizer, true
    setting :ignore_file_names, default: false # before: setting :ignore_file_names, false
  end

Now it's starting without errors and warnings, but the state variable from the example is receiving nothing from this block:

  state = nil

  client.on(TD::Types::Update::AuthorizationState) do |update|
    state =
      case update.authorization_state
      when TD::Types::AuthorizationState::WaitPhoneNumber
        :wait_phone_number
      when TD::Types::AuthorizationState::WaitCode
        :wait_code
      when TD::Types::AuthorizationState::WaitPassword
        :wait_password
      when TD::Types::AuthorizationState::Ready
        :ready
      end
  end

And my code is just busy. But as I got it, it should show me the prompt to put my phone and so on.

From: /home/user/coding/tapp/tel.rb:37 :

    32:   end
    33: 
    34:   client.connect
    35: 
    36:   loop do
 => 37:     binding.pry
    38: 
    39:     case state
    40:     when :wait_phone_number
    41:       puts 'Please, enter your phone number:'
    42:       phone = STDIN.gets.strip

[1] pry(main)> client
=> #<TD::Client:0x00007fe836fdd858
 @alive=true,
 @config=
  {:api_id=>"----------", # my real API ID is shown here
   :api_hash=>"----------------------------", # and the API Hash too
   :use_test_dc=>false,
   :database_directory=>"/home/user/.tdlib-ruby/db",
   :files_directory=>"/home/user/.tdlib-ruby/data",
   :use_file_database=>true,
   :use_chat_info_database=>true,
   :use_secret_chats=>true,
   :use_message_database=>true,
   :system_language_code=>"en",
   :device_model=>"Ruby TD client",
   :system_version=>"Unknown",
   :application_version=>"1.0",
   :enable_storage_optimizer=>true,
   :ignore_file_names=>false},
[2] pry(main)> state
=> nil
[3] pry(main)> !!!

Do you have any idea on how to fix it, guys?

olegzakharov1416 commented 1 year ago

@yart Write if you can solve this problem. I’m also struggling with it now, I have no ideas.

yart commented 1 year ago

@yart Write if you can solve this problem. I’m also struggling with it now, I have no ideas.

Sure. I have an assumption that the problem in one of the following places:

  1. Incorrectly built TDlib — I've been built it using g++ v.13.2.1 installed on Archlinux. I have Clang too, but it produces a strange error when I'm trying to compile the library using this one. So, I'm going to do the following to resolve this possible trouble: a. Install TDlib from AUR — it has one b. Try to compile it in a Docker container (or find a ready one) with Ubuntu or Alpine and clang
  2. TDlib was changed and needs another set of parameters, so the current one should be changed to the actual state. Will read the TDlib docs to check it.
  3. Some insignificant changes in dry-rb (like it happened with dry-configurable, but not so fatal) or/and in concurrent-ruby. Will read the sources and the change logs to check it.
KonstantinReido commented 8 months ago

@yart did you find a solution?

yart commented 8 months ago

@yart did you find a solution?

@KonstantinReido I didn't have a time for this yet. But I remember about the problem.

chhlga commented 5 months ago

Tdlib changed input params for setTdlibParameters.

https://github.com/tdlib/td/issues/2211#issuecomment-1327625869

tilvin commented 5 months ago

Let me share my experience how to work with this lib:

  1. Install TDlib from original resource https://tdlib.github.io/td/build.html?language=Ruby. Tick V Install built TDLib to /usr/local instead of placing the files to td/tdlib.

  2. Fork schema https://github.com/southbridgeio/tdlib-schema is old and dusty, you will have to fork iе. Add this PR and add some other changes.

The most important one is to change set_tdlib_parameters method to cover this changes in TDlib:

def set_tdlib_parameters(parameters:)
   broadcast(parameters.to_hash.merge('@type' => 'setTdlibParameters'))
end

Also i'm trying to inline schema with Tdlib, maybe i will create a PR soon, but at the moment you can check my fork https://github.com/tilvin/tdlib-schema.

  1. Then authorize:
TD.configure do |config|    
  config.client.api_id = 'api_id'
  config.client.api_hash = 'api_hash'
end
TD::Api.set_log_verbosity_level(1)

client = TD::Client.new

Add debugging puts:

client.on(TD::Types::Update::AuthorizationState) do |update|
   puts "----->  #{update.inspect}"
end
  1. Then connect:

client.connect

  1. Now you suppose to see the auth requirements, something like WaitPhoneNumber.

Pick method from ClientMethods accordingly.

client.set_authentication_phone_number(phone_number: '+7 phone', settings: nil).wait
—> code comes to TG

client.check_authentication_code(code: 'your code’)
  1. Check if it's alive
    client.on('updateNewMessage') do |update|
    puts "========> NEWS updateNewMessage #{update.inspect}"
    end
  2. Tips You might see notifications like: Uncaught exception in update manager: [TD::Types::ScopeNotificationSettings.new] :sound is missing in Hash input Uncaught exception in update manager: Can't find class for updateChatFolders Uncaught exception in update manager: Can't find class for updateStoryStealthMode

It comes from rescue, and means that e.g schema's class ScopeNotificationSettings attributes doesn't match with TDlib scopeNotificationSettings anymore. And Tdlib has updateChatFolders class, but your schema don't.

vladimir-vg commented 4 months ago

The most important one is to change set_tdlib_parameters method to cover this changes in TDlib:

Hm, on my machine it doesn't see .merge method for TD::Types::TdlibParameters, which is a subclass of Dry::Struct:

-----> #<TD::Types::Update::AuthorizationState authorization_state=#<TD::Types::AuthorizationState::WaitTdlibParameters>>
Uncaught exception in handler TD::UpdateHandler (TD::Types::Update::AuthorizationState): undefined method `merge' for an instance of TD::Types::TdlibParameters

I've used gem 'dry-configurable', '0.15.0', otherwise it just refuses to load tdlib-ruby with no receiver given message.

Tried to replace .merge with .new, with no luck for now.

tilvin commented 4 months ago

The most important one is to change set_tdlib_parameters method to cover this changes in TDlib:

Hm, on my machine it doesn't see .merge method for TD::Types::TdlibParameters, which is a subclass of Dry::Struct:

-----> #<TD::Types::Update::AuthorizationState authorization_state=#<TD::Types::AuthorizationState::WaitTdlibParameters>>
Uncaught exception in handler TD::UpdateHandler (TD::Types::Update::AuthorizationState): undefined method `merge' for an instance of TD::Types::TdlibParameters

I've used gem 'dry-configurable', '0.15.0', otherwise it just refuses to load tdlib-ruby with no receiver given message.

Tried to replace .merge with .new, with no luck for now.

Thanks, i forgot this part: a small update set_tdlib_parameters(parameters: TD::Types::TdlibParameters.new(**@config).to_hash) here

Or

def set_tdlib_parameters(parameters:)
   broadcast(parameters.to_hash.merge('@type' => 'setTdlibParameters'))
end

to change only one gem instead of two.

vladimir-vg commented 4 months ago

Thanks, i forgot this part: a small update

Thanks! Indeed, this fix made that error disappear

tim08 commented 1 week ago

Can anyone tell me what the current set of dependencies is? My current set:

i changed client.rb

  def connect
    on TD::Types::Update::AuthorizationState do |update|
      case update.authorization_state
      when TD::Types::AuthorizationState::WaitTdlibParameters
        # set_tdlib_parameters(parameters: TD::Types::TdlibParameters.new(**@config))
        set_tdlib_parameters(parameters: TD::Types::TdlibParameters.new(**@config).to_hash)
      when TD::Types::AuthorizationState::WaitEncryptionKey
        check_database_encryption_key(encryption_key: TD.config.encryption_key).then do
          @ready_condition_mutex.synchronize do
            @ready = true
            @ready_condition.broadcast
          end
        end
      else
        # do nothing
      end
    end

    @update_manager.run(callback: method(:handle_update))
    ready
  end

I get an error when running the example from the readme (I commented out the logging line to get more information):

C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/dry-configurable-0.15.0/lib/dry/configurable/dsl.rb:28:in `initialize' [dry-configurable] passing a constructor as a block is deprecated and will be removed in the next major version
Provide a `constructor:` keyword argument instead

[ 3][t 5][1732479222.650855302][Td.cpp:2668][#1][!MultiTd]      Create Td with layer 135, database version 13 and version 35 on 4 threads
[ 3][t 5][1732479222.650944709][Td.cpp:4062][#1][!Td][&td_requests]     Sending update: updateOption {
  name = "version"
  value = optionValueString {
    value = "1.8.0"
  }
}
[ 3][t 5][1732479222.650986671][Td.cpp:4062][#1][!Td][&td_requests]     Sending update: updateAuthorizationState {
  authorization_state = authorizationStateWaitTdlibParameters {
  }
}
[ 3][t 0][1732479222.661797285][Client.cpp:278][&td_requests]   Begin to wait for updates with timeout 30.000000
[ 3][t 0][1732479222.669217824][Client.cpp:291][&td_requests]   End to wait for updates, returning object 0 000001D155E5A5A0
[ 3][t 0][1732479222.689413547][Client.cpp:278][&td_requests]   Begin to wait for updates with timeout 30.000000
[ 3][t 0][1732479222.689558029][Client.cpp:291][&td_requests]   End to wait for updates, returning object 0 000001D1566F67E0
----->  #<TD::Types::Update::AuthorizationState authorization_state=#<TD::Types::AuthorizationState::WaitTdlibParameters>>
[ 3][t 5][1732479222.696928501][Td.cpp:3030][#1][!Td][&td_requests]     Receive request 1: setTdlibParameters {
  parameters = null
}
[ 3][t 5][1732479222.696987390][Td.cpp:4091][#1][!Td][&td_requests]     Sending error for request 1: error { code = 400 message = "Parameters aren't specified" }
[ 3][t 0][1732479222.704432964][Client.cpp:278][&td_requests]   Begin to wait for updates with timeout 30.000000

p.s. I don't know how important it is, but I had to rename tdjson.dll to libtdjson.dll after compilation tdLib, otherwise I'd get an error:

C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/ffi-1.15.5-x64-mingw-ucrt/lib/ffi/library.rb:145:in `block in ffi_lib': Could not open library 'C:/projects//telegram_c/libtdjson.dll
tilvin commented 1 week ago

Can anyone tell me what the current set of dependencies is? My current set:

i changed client.rb

  def connect
    on TD::Types::Update::AuthorizationState do |update|
      case update.authorization_state
      when TD::Types::AuthorizationState::WaitTdlibParameters
        # set_tdlib_parameters(parameters: TD::Types::TdlibParameters.new(**@config))
        set_tdlib_parameters(parameters: TD::Types::TdlibParameters.new(**@config).to_hash)
      when TD::Types::AuthorizationState::WaitEncryptionKey
        check_database_encryption_key(encryption_key: TD.config.encryption_key).then do
          @ready_condition_mutex.synchronize do
            @ready = true
            @ready_condition.broadcast
          end
        end
      else
        # do nothing
      end
    end

    @update_manager.run(callback: method(:handle_update))
    ready
  end

I get an error when running the example from the readme (I commented out the logging line to get more information):

C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/dry-configurable-0.15.0/lib/dry/configurable/dsl.rb:28:in `initialize' [dry-configurable] passing a constructor as a block is deprecated and will be removed in the next major version
Provide a `constructor:` keyword argument instead

[ 3][t 5][1732479222.650855302][Td.cpp:2668][#1][!MultiTd]      Create Td with layer 135, database version 13 and version 35 on 4 threads
[ 3][t 5][1732479222.650944709][Td.cpp:4062][#1][!Td][&td_requests]     Sending update: updateOption {
  name = "version"
  value = optionValueString {
    value = "1.8.0"
  }
}
[ 3][t 5][1732479222.650986671][Td.cpp:4062][#1][!Td][&td_requests]     Sending update: updateAuthorizationState {
  authorization_state = authorizationStateWaitTdlibParameters {
  }
}
[ 3][t 0][1732479222.661797285][Client.cpp:278][&td_requests]   Begin to wait for updates with timeout 30.000000
[ 3][t 0][1732479222.669217824][Client.cpp:291][&td_requests]   End to wait for updates, returning object 0 000001D155E5A5A0
[ 3][t 0][1732479222.689413547][Client.cpp:278][&td_requests]   Begin to wait for updates with timeout 30.000000
[ 3][t 0][1732479222.689558029][Client.cpp:291][&td_requests]   End to wait for updates, returning object 0 000001D1566F67E0
----->  #<TD::Types::Update::AuthorizationState authorization_state=#<TD::Types::AuthorizationState::WaitTdlibParameters>>
[ 3][t 5][1732479222.696928501][Td.cpp:3030][#1][!Td][&td_requests]     Receive request 1: setTdlibParameters {
  parameters = null
}
[ 3][t 5][1732479222.696987390][Td.cpp:4091][#1][!Td][&td_requests]     Sending error for request 1: error { code = 400 message = "Parameters aren't specified" }
[ 3][t 0][1732479222.704432964][Client.cpp:278][&td_requests]   Begin to wait for updates with timeout 30.000000

p.s. I don't know how important it is, but I had to rename tdjson.dll to libtdjson.dll after compilation tdLib, otherwise I'd get an error:

C:/Ruby31-x64/lib/ruby/gems/3.1.0/gems/ffi-1.15.5-x64-mingw-ucrt/lib/ffi/library.rb:145:in `block in ffi_lib': Could not open library 'C:/projects//telegram_c/libtdjson.dll

Hello, there were major updates introduces in 'tdlib-schema' and 'tdlib-ruby' a few month ago, so i suggest you to use those gems with master branches. 'tdlib-schema' (master branch) is a little bit behind current TDLib version, but at least you should be able to login.

tim08 commented 1 week ago

@tilvin thanks for the answer, which version should I use TDLib https://github.com/tdlib/td : master or v1.8.0 ?

tilvin commented 1 week ago

@tilvin thanks for the answer, which version should I use TDLib https://github.com/tdlib/td : master or v1.8.0 master

tim08 commented 4 days ago

this might come in handy. I got the authorisation and method of receiving messages from the channel working(text and photo), but when I'm trying to get a video post:

Uncaught exception in update manager: Attribute :video has already been defined

I saw at the very bottom of the documentation information about using ./bin/parse and tried to run:

C:/tg/tdlib-schema/bin/parser:403:in `sort_by': comparison of NilClass with String failed (ArgumentError)
        from C:/tg/tdlib-schema/bin/parser:403:in `<main>'

be sure to take note of: https://github.com/southbridgeio/tdlib-schema/blob/master/bin/parser#L3 After that, everything worked.