I use curl to update my public channels. This kind of syntax:
curl -X POST "https://api.telegram.org/bot144377327:AAGqdElkZ-77zsPRoAXXXXXXXXXX/sendMessage" -d "chat_id=#MyChannel&text=my sample text"
But what's the chat_id of a private channel? It's not the one you have in the private invite.
Because now we can pass a channel username (in the format #channelusername) in the place of chat_id in all methods (and instead of from_chat_id in forwardMessage). But what's the #channelusername of a private channel that I administer?
I found the way to write in private channels.
You should convert it to public with some #channelName
Send a message to this channel through the Bot API:
https://api.telegram.org/bot111:222/sendMessage?chat_id=#channelName&text=123
As the response, you will get information with chat_id of your channel.
{
"ok" : true,
"result" : {
"chat" : {
**"id" : -1001005582487,**
"title" : "Test Private Channel",
"type" : "channel"
},
"date" : 1448245538,
"message_id" : 7,
"text" : "123ds"
}
}
Now you can convert the channel back to private (by deleting the channel's link) and send a message directly to the chat_id "-1001005582487":
https://api.telegram.org/bot111:222/sendMessage?chat_id=-1001005582487&text=123
The easiest way:
Just send your invite link to your private channel to #username_to_id_bot (https://t.me/username_to_id_bot) bot. It will return its ID. The simplest level: maximum! :)
PS. I am not an owner of this bot.
PS 2. the Bot will not join your group, but to be sure in security. Just revoke your old invitation link if it is matter for you after bot using.
A more cumbersome way:
Making the channel public cannot be done by the user with exist at least five public groups/channels, so...the problem is not solved. Yes, you can revoke one of them, but for now, we cannot retrieve chat id another way.
Another one working solution:
log in under your account at web version of Telegram: https://web.telegram.org
updated (thanks #Julian Espinel) Find your channel. See to your URL. It should be like https://web.telegram.org/z/#-1543515057
Grab "1543515057" from it, and add "-100" as a prefix.
So... your channel id will be "-1001543515057". Magic happens :)
The solution was found at Web Channel ID .
Open the private channel, then:
on web client:
look at the URL in your browser:
if it's for example https://web.telegram.org/#/im?p=c1192292378_2674311763110923980
then 1192292378 is the channel ID
on mobile and desktop:
copy the link of any message of the channel:
if it's for example https://t.me/c/1192292378/31
then 1192292378 is the channel ID (bonus: 31 is the message ID)
on Plus Messenger for Android:
open the infos of the channel:
the channel ID appears above, right under its name
WARNING be sure to add -100 prefix when using Telegram Bot API:
if the channel ID is for example 1192292378
then you should use -1001192292378
The easiest way is to invite #get_id_bot in your chat and then type:
/my_id #get_id_bot
Inside your chat
Actually, it is pretty simple.
All you need to do is to:
Invite the bot to the channel/group (doesn't matter private or not).
Send any message in the channel/group.
Go to getUpdates API URL in the browser:
https://api.telegram.org/bot<BOT_TOKEN>/getUpdates
Now, look at the results.
You will see a JSON output.
In this JSON, look for the chat data. Usually, latest updates are at the end.
{
"ok":true,
"result":[
...
{
...
"my_chat_member":{
"chat":{
"id":-100987654321,
"title":"My Channel",
"type":"channel"
},
...
}
}
]
}
Your chat ID is -100987654321.
Open Telegram Web at https://web.telegram.org
Search your private channel
Look at the URL. It's like:
https://web.telegram.org/#/im?p=cXXXXXXXXXX_578236787445474833
The id of your private channel is the XXXXXX part (between the "p=c" and the underscore).
To use it, just add "-100" in front of it. So if "XXXXXX" is "4785444554" your private channel id is "-1004785444554".
For now you can write an invite link to bot #username_to_id_bot and you will get the id:
Example:
It also works with public chats, channels and even users.
You can also do this:
Step 1. Convert your private channel to a public channel
Step 2. Set the ChannelName for this channel
Step 3. Then you can change this channel to private
Step 4. Now sending your message using #ChannelName that you set in step 3
Note: For Step 1, you can change one of your public channels to private for a short time.
There isn't any need to convert the channel to public and then make it private.
find the id of your private channel. (There are numerous methods to do this, for example see this Stack Overflow answer.)
curl -X POST "https://api.telegram.org/botxxxxxx:yyyyyyyyyyy/sendMessage" -d
"chat_id=-100CHAT_ID&text=my sample text"
Replace xxxxxx:yyyyyyyyyyy with your bot id, and replace CHAT_ID with the channel id found in step 1. So if the channel id is 1234, it would be chat_id=-1001234.
All done!
Simply and easy; just pass the channel username and it will show you the id:
from telethon.sync import TelegramClient, events
client = TelegramClient("bot", API_ID, API_HASH)
channel_name = "channel username"
channel = client.get_entity(channel_name)
print(f'👉 Channel ID: {channel.id}')
client.start()
client.run_until_disconnected()
The option that I do is by using the popular Plus Messenger on Android.
You can click on the channel and in Channel info below the group name, you can find the channel Id.
Supergroup and channel ids will look like 1068773197 on Plus Messenger. For your usage on API, you can prefix -100 which would make it -1001068773197.
I found the solution for TelegramBotApi for Python. Maybe it will work for other languages.
I just add my bot to the private channel and then do this:
#your_bot_name hi
In the console I get a response with all the information that I need.
I used Telegram.Bot and got the ID the following way:
Add the bot to the channel
Run the bot
Write something into the channel (for example, /authenticate or foo)
Telegram.Bot:
private static async Task Main()
{
var botClient = new TelegramBotClient("key");
botClient.OnUpdate += BotClientOnOnUpdate;
Console.ReadKey();
}
private static async void BotClientOnOnUpdate(object? sender, UpdateEventArgs e)
{
var id = e.Update.ChannelPost.Chat.Id;
await botClient.SendTextMessageAsync(new ChatId(id), $"Hello World! Channel ID is {id}");
}
Plain API:
This translates to the getUpdates method in the plain API, which has an array of update which then contains channel_post.chat.id.
Yet another way to use JavaScript and the Axios library. So you might want to explore /getUpdates method of Telegram API:
const headers: any = {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
timestamp: +new Date(),
}
const options = { headers: { ...headers } }
const urlTelegramBase =
'https://api.telegram.org/bot123456:ABCDEF'
const urlGetUpdates = `${urlTelegramBase}/getUpdates`
const username = 'user_name'
const {
data: { result: messages },
} = await axios.get(urlGetUpdates, options)
const chat_id = messages.find(
messageBlock => messageBlock.message.chat.username === username
).message.chat.id
console.info('chat_id': chat_id)
Run this command in your terminal.
curl https://api.telegram.org/bot{your_bot_token}/getUpdates
But You have added your bot to your private channel.You will get your private channel chat id in json response.
You should add and make your bot an administrator of the private channel. Otherwise, the chat not found error happens.
Related
im trying to make it possible for a room host to kick a user, im using the rest api to kick a user, when i send a request with the following body:
public CompletableFuture<Boolean> actionOnUser(String action, Long channelId, String userId) {
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>();
Map body = new HashMap<>();
body.put("appid", agoraConfig.getAppId());
body.put("uid", userId);
body.put("time", 0);
body.put("cname", channelId.toString());
body.put("ip", "");
String[] privileges = { action };
body.put("privileges", privileges);
Mono<String> agoraResponse = webClient().post().uri("/dev/v1/kicking-rule").bodyValue(body).retrieve()
.bodyToMono(String.class).doOnSuccess(response -> {
logger.info("kicking-rule response status:" + response);
completableFuture.complete(true);
}).doOnError(onError -> {
logger.info("kicking rule failed" + onError);
completableFuture.complete(false);
});
agoraResponse.subscribe();
return completableFuture;
}
i get a 200 OK response with an id of the kicking rule, but the user isn't being kicked, how can i fix this?
Edit: apparently agora doesnt accept strings as uid, had to switch to int which is unfortunate because i preferred to use UUID, but this fixes the issue
agora doesnt accept strings as uid, had to switch to int which is unfortunate because i preferred to use UUID, but this fixes the issue
For implementing kick user from call functionality you can use Agora RTM SDK.
For ref:- https://www.agora.io/en/blog/muting-and-unmuting-a-remote-user-in-a-video-call-web/
Also, you can use your custom WebSocket.
After a connection to the socket.io server a socket.id is given for the connection. When the socket connection has not been used after some time a new socket id is generated.
I have read a lot of tutorials that do a "hello world" connection that just gets you connected, but, there is not much literature on messaging peer-to-peer/group. The docs give a 3 line paragraph on rooms/namespaces and every question related to this is just given a link to the same 3 line paragraph.
I understand that you can create and object/array of chats(in this example). For this example, let's say it is an object. That Object looks something like this:
const connections = {
"randomSocketID1": {
recipient: "Mom",
messages: [Array of Objects]
//more information
}
}
I then send a message to randomSocketID1 --> 'Hello'. Then next day I want to send another message to "Mom". Is that socketID going to be the same OR AT LEAST will "randomSocketID1" be updated under the hood, to its updated ID(which sounds improbable)? Is the regeneration of the socketID a product of garbage collection or a socket/engine/websocket protocol?
thanks for any clarification
So I was still unable to find an actual answer to this and by the 0 responses i see that no one knows. So what I have done in order to make sure that user and socket id are maintained is whenever a user enters the component that connects to the socketio server an automatic 'update-user' is emitted and the back end then just finds the user and assigns it the value.
So I have something like this:
chat.component.ts:
ngOnInit(){
this.socket.emit('update-user', 'Ctfrancia');
}
then in the back end:
const users = {};
io.on('connection', socket => {
socket.on('update-user', user => {
if (user in users) users[user] = socket.id;
else users[user] = socket.id
});
});
I am learning using youtube data api v3 to show list of playlists and further show list of videos of each play list from below link
https://developers.google.com/youtube/v3
I was able to get playlist for a channel id. And further each playlist, list of videos.
Before that I need channel id to do rest of operations. The input would be name of the channel and output should be details which includes unique channel id.
Below is the code snip that I was trying but I always get null result. Where as other part of code (by hard coding channel id) works great.
public class GetChannelInfoAsyncTask extends AsyncTask<String, Void, ChannelListResponse> {
private static final String YOUTUBE_CHANNELLIST_PART = "snippet";
private static final String YOUTUBE_CHANNELLIST_FIELDS = "items(id,snippet(title))";
private YouTube mYouTubeDataApi;
public GetChannelInfoAsyncTask(YouTube api) {
mYouTubeDataApi = api;
}
#Override
protected ChannelListResponse doInBackground(String... params) {
final String channelName = params[0];
ChannelListResponse channelListResponse = null;
try {
channelListResponse = mYouTubeDataApi.channels()
.list(YOUTUBE_CHANNELLIST_PART)
.setForUsername(channelName)
.setAlt(ApiKey.YOUTUBE_API_KEY)
.execute();
} catch (IOException e) {
e.printStackTrace();
}
return channelListResponse;
}
}
Referring to
https://developers.google.com/youtube/v3/docs/channels/list
and tried EXECUTE option with list (by YouTube username) gives 200(OK) success. but with above code its always null.
I came too late, but I have an answer. To get a Youtube channel's ID via v3 API make a HTTP GET request to https://www.googleapis.com/youtube/v3/search with these params:
part=snippet
type=channel
fields=items%2Fsnippet%2FchannelId
q={YOUTUBE_CHANNEL_NAME}
key={YOUR_API_KEY}
Change value for fields key if you need more info.
Try it here
Official Guide: Work with Channel IDs
Youtube data v3 API: Here is the get request to find channel_id by channel name
https://www.googleapis.com/youtube/v3/channels?forUsername={CHANNEL_NAME}&part=snippet,id&key={API_KEY}
I'm having no luck getting a response from v4 of the Google Sheets API when running against a public (i.e. "Published To The Web" AND shared with "Anyone On The Web") spreadsheet.
The relevant documentation states:
"If the request doesn't require authorization (such as a request for public data), then the application must provide either the API key or an OAuth 2.0 token, or both—whatever option is most convenient for you."
And to provide the API key, the documentation states:
"After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs."
So, I should be able to get a response listing the sheets in a public spreadsheet at the following URL:
https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}?key={myAPIkey}
(with, obviously, the id and key supplied in the path and query string respectively)
However, when I do this, I get an HTTP 401 response:
{
error: {
code: 401,
message: "The request does not have valid authentication credentials.",
status: "UNAUTHENTICATED"
}
}
Can anyone else get this to work against a public workbook? If not, can anyone monitoring this thread from the Google side either comment or provide a working sample?
I managed to get this working. Even I was frustrated at first. And, this is not a bug. Here's how I did it:
First, enable these in your GDC to get rid of authentication errors.
-Google Apps Script Execution API
-Google Sheets API
Note: Make sure the Google account you used in GDC must be the same account you're using in Spreadsheet project else you might get a "The API Key and the authentication credential are from different projects" error message.
Go to https://developers.google.com/oauthplayground where you will acquire authorization tokens.
On Step 1, choose Google Sheets API v4 and choose https://www.googleapis.com/auth/spreadsheets scope so you have bot read and write permissions.
Click the Authorize APIs button. Allow the authentication and you'll proceed to Step 2.
On Step 2, click Exchange authorization code for tokens button. After that, proceed to Step 3.
On Step 3, time to paste your URL request. Since default server method is GET proceed and click Send the request button.
Note: Make sure your URL requests are the ones indicated in the Spreadsheetv4 docs.
Here's my sample URL request:
https://sheets.googleapis.com/v4/spreadsheets/SPREADSHEET_ID?includeGridData=false
I got a HTTP/1.1 200 OK and it displayed my requested data. This goes for all Spreadsheetv4 server-side processes.
Hope this helps.
We recently fixed this and it should now be working. Sorry for the troubles, please try again.
The document must be shared to "Anyone with the link" or "Public on the web". (Note: the publishing settings from "File -> Publish to the web" are irrelevant, unlike in the v3 API.)
This is not a solution of the problem but I think this is a good way to achieve the goal. On site http://embedded-lab.com/blog/post-data-google-sheets-using-esp8266/ I found how to update spreadsheet using Google Apps Script. This is an example with GET method. I will try to show you POST method with JSON format.
How to POST:
Create Google Spreadsheet, in the tab Tools > Script Editor paste following script. Modify the script by entering the appropriate spreadsheet ID and Sheet tab name (Line 27 and 28 in the script).
function doPost(e)
{
var success = false;
if (e != null)
{
var JSON_RawContent = e.postData.contents;
var PersonalData = JSON.parse(JSON_RawContent);
success = SaveData(
PersonalData.Name,
PersonalData.Age,
PersonalData.Phone
);
}
// Return plain text Output
return ContentService.createTextOutput("Data saved: " + success);
}
function SaveData(Name, Age, Phone)
{
try
{
var dateTime = new Date();
// Paste the URL of the Google Sheets starting from https thru /edit
// For e.g.: https://docs.google.com/---YOUR SPREADSHEET ID---/edit
var MyPersonalMatrix = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/---YOUR SPREADSHEET ID---/edit");
var MyBasicPersonalData = MyPersonalMatrix.getSheetByName("BasicPersonalData");
// Get last edited row
var row = MyBasicPersonalData.getLastRow() + 1;
MyBasicPersonalData.getRange("A" + row).setValue(Name);
MyBasicPersonalData.getRange("B" + row).setValue(Age);
MyBasicPersonalData.getRange("C" + row).setValue(Phone);
return true;
}
catch(error)
{
return false;
}
}
Now save the script and go to tab Publish > Deploy as Web App.
Execute the app as: Me xyz#gmail.com,
Who has access to the app: Anyone, even anonymous
Then to test you can use Postman app.
Or using UWP:
private async void Button_Click(object sender, RoutedEventArgs e)
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(#"https://script.google.com/");
httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("utf-8"));
string endpoint = #"/macros/s/---YOUR SCRIPT ID---/exec";
try
{
PersonalData personalData = new PersonalData();
personalData.Name = "Jarek";
personalData.Age = "34";
personalData.Phone = "111 222 333";
HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(personalData), Encoding.UTF8, "application/json");
HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(endpoint, httpContent);
if (httpResponseMessage.IsSuccessStatusCode)
{
string jsonResponse = await httpResponseMessage.Content.ReadAsStringAsync();
//do something with json response here
}
}
catch (Exception ex)
{
}
}
}
public class PersonalData
{
public string Name;
public string Age;
public string Phone;
}
To above code NuGet Newtonsoft.Json is required.
Result:
If your feed is public and you are using api key, make sure you are throwing a http GET request.In case of POST request, you will receive this error.
I faced same.
Getting data using
Method: spreadsheets.getByDataFilter has POST request
Any ideas on how can I list all the activities in my domain by using the new google+ domain's API in java?
The Developers' Live video shows at 4:00 minute mark that you can do something like this:
Plus.Activities.List listActivities = plus.activities().list("me", "domain");
The Link for this code is here.
But when I actually run the same line of code it shows me the following error.
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"location" : "collection",
"locationType" : "parameter",
"message" : "Invalid string value: 'domain'. Allowed values: [user]",
"reason" : "invalidParameter"
} ],
"message" : "Invalid string value: 'domain'. Allowed values: [user]"
}
The error makes sense as in the activities.list documentation it says that "user" is the only acceptable value for collection and not "domain."
So what should I do about this issue?
As you say, the only available way is to list posts by the currently logged user. You have to use user delegation (with service accounts) and loop over all users in the domain in order to get all published activities.
You can use the updated field on the response to check if there is anything new in a user's list of activities.
This line of thought applies to the whole Domains API: every operation is done on behalf of a user, there is no "admin" account with superpowers. This can be a limitation when acting on a big number of users, as you are forced to authenticate for each one in turn (if someone has an idea on how to achieve this in a more efficient way, please share!)
As the documentation sais, only "public" is allowed:
https://developers.google.com/+/api/latest/activities/list
However even using the code provided in the example in the API doc, after going through successful authentication I get 0 activities.
/** List the public activities for the authenticated user. */
private static void listActivities() throws IOException {
System.out.println("Listing My Activities");
// Fetch the first page of activities
Plus.Activities.List listActivities = plus.activities().list("me", "public");
listActivities.setMaxResults(100L);
// Pro tip: Use partial responses to improve response time considerably
listActivities.setFields("nextPageToken,items(id,url,object/content)");
ActivityFeed activityFeed = listActivities.execute();
// Unwrap the request and extract the pieces we want
List<Activity> activities = activityFeed.getItems();
System.out.println("Number of activities: " + activities.size());
// Loop through until we arrive at an empty page
while (activities != null) {
for (Activity activity : activities) {
System.out.println("ID " + activity.getId() + " Content: " +
activity.getObject().getContent());
}
// We will know we are on the last page when the next page token is null.
// If this is the case, break.
if (activityFeed.getNextPageToken() == null) {
break;
}
// Prepare to request the next page of activities
listActivities.setPageToken(activityFeed.getNextPageToken());
// Execute and process the next page request
activityFeed = listActivities.execute();
activities = activityFeed.getItems();
}
}
Anybody know how to get this to work?
when you use Google+ API you must use "public" but when you use Google+ Domains API you must use "user" parameter value.