MadelineProto Join more than one group/channel at once - php

I use MadelineProtoDocs to create a userbot that do tasks I want. What I want to do is that I want to Join more than one group at once!
I have used
$MadelineProto->messages->importChatInvite(['hash' => 'HASH_CODE']);
It works when I put a hashcode for one group, but when I put more than one like this:
$MadelineProto->messages->importChatInvite(['hash' => ['HASH_CODE', 'HASH_CODE2']);
it doesn’t work
I also tried:
$MadelineProto->channels->joinChannel(['channel' => [InputChannel, InputChannel], ]);
it also doesn’t work!

I found the solution.
It’s easy to do that
So when you join a channel or group you do this:
$join = yield $MadelineProto->channels->joinChannel(['channel' => '#channelusername', ]);
By this you will join only one channel/group,
so how to add another channel/group in the same code?
It’s easy:
$join =
yield $MadelineProto->channels->joinChannel(['channel' => '#channelusername', ]);
yield $MadelineProto->channels->joinChannel(['channel' => '#channelusername1', ]);
yield $MadelineProto->channels->joinChannel(['channel' => '#channelusername2', ]);
and you will join all the channels you added!

Related

CakePHP 3 - use different table aliases when separating JOIN conditions

I'm rebuilding a vanilla PHP/MySQL application using CakePHP 3.5.13.
One of the queries in the original application needs to build a JOIN condition on the same table and does so by using separate table aliases. The query is as follows - and gives the correct results that we expect:
SELECT DISTINCT(s.id) FROM substances s
JOIN display_substances AS dsUses
ON (s.id = dsUses.substance_id AND dsUses.display_id = 128 AND (dsUses.value LIKE '%dye%') )
JOIN display_substances AS displays
ON (s.id = displays.substance_id AND displays.display_id NOT IN (1,2,3,4,6,128) AND (displays.value LIKE '%bpr%'))
The reason this is needed is because the query is doing a search for 2 separate items of user input - within the same table (display_substances) but against different display_substances .display_id fields. In terms of the query above it means:
Search for "%dye%" where display_id = 128
Search for "%bpr%" where display_id is not 1,2,3,4,6 or 128
In Cake I have written it like this in a Controller that handles the search functionality:
$query = $Substances->find()->select(['id' => 'Substances.id'])->distinct();
// Search for "dye"
$query = $query->matching('DisplaySubstances', function ($q) use ($uses_summary) {
return $q->where([
'DisplaySubstances.value LIKE' => '%dye%', // "dye" is dynamic and comes from $uses_summary
'DisplaySubstances.display_id' => 128
]);
});
// Search for "bpr"
$query = $query->matching('DisplaySubstances', function ($q) use ($regulatory_information) {
return $q->where([
'DisplaySubstances.value LIKE' => '%bpr%', // "bpr" is dynamic and comes from $regulatory_information
'DisplaySubstances.display_id NOT IN' => [1,2,3,4,6,128]
]);
});
This produces the wrong SQL, because when I debug $query->sql(); it gives a different JOIN condition:
INNER JOIN display_substances DisplaySubstances ON
(
DisplaySubstances.value like "%dye%" AND DisplaySubstances.display_id = 128
AND DisplaySubstances.value like "%bpr%"
AND DisplaySubstances.display_id not in (1,2,3,4,6,128)
AND Substances.id = (DisplaySubstances.substance_id)
)
I'm not sure how to rewrite this query such that it will treat each of the two search inputs as a JOIN condition, as per the original query.
The main thing I've noticed is that the original query has separate aliases for the same table (AS dsUses and AS displays). I'm not sure if this is relevant?
I'm trying to use the ORM as opposed to writing the SQL manually so would prefer to know how to use it to do this.
It's not yet possible to specify custom aliases for matching() calls, currently multiple matching() calls on the same association will merge the conditions as can be seen in your generated SQL snippet.
For now you'd have to either create additional associations (ie additionally to your DisplaySubstances association in your SubstancesTable class) with different aliases:
$this->hasMany('DsUses', [
'className' => 'DisplaySubstances'
]);
$this->hasMany('Displays', [
'className' => 'DisplaySubstances'
]);
on which you can then match:
$query->matching('DsUses', function ($q) use ($regulatory_information) {
return $q->where([
'DsUses.value LIKE' => '%dye%',
'DsUses.display_id' => 128
]);
});
$query->matching('Displays', function ($q) use ($regulatory_information) {
return $q->where([
'Displays.value LIKE' => '%bpr%',
'Displays.display_id NOT IN' => [1, 2, 3, 4, 6, 128]
]);
});
or build the joins manually, for example using innerJoin():
$query->innerJoin(
[
'DsUses' => 'display_substances'
],
[
'Substances.id' => new \Cake\Database\Expression\IdentifierExpression('DsUses.substance_id'),
'DsUses.display_id' => 128,
'DsUses.value LIKE' => '%dye%'
],
[
'DsUses.display_id' => 'integer',
'DsUses.value' => 'string'
]
);
$query->innerJoin(
[
'Displays' => 'display_substances'
],
[
'Substances.id' => new \Cake\Database\Expression\IdentifierExpression('Displays.substance_id'),
'Displays.display_id NOT IN' => [1, 2, 3, 4, 6, 128],
'Displays.value LIKE' => '%bpr%'
],
[
'Displays.display_id' => 'integer',
'Displays.value' => 'string'
]
);
See also
cakephp/cakephp#9499 : Improve association data fetching
Cookbook > Database Access & ORM > Query Builder > Adding Joins

Yii relations subquery

This is the query I have:
select * from order_shipping_date osd inner join
(SELECT MAX(osd.id) as id FROM order_shipping_date osd
group by osd.order_id) osdi ON osd.id = osdi.id
I'm fine with keeping it so, but would like to make it possible to define it as relations
This is more comfy to use such code later
Is this doable at all? I can't find any examples.
Additional options can be specified in relationship declaration.
public function relations()
{
return array(
'orderShippingDate' => array(
// define you relation
'join' => '(/* subquery here*/) osdi ON osdi.id=orderShippingDate.id',
'joinType' => 'INNER JOIN'
),
);
}

Yii2 viaTable join condition

Is it possible to set condition in join section in viaTable?
Currently I got this:
return $this->hasMany(User::className(), ['id' => 'id_user'])
->from(User::tableName())
->viaTable(RoomActiveUser::tableName(), ['id_room' => 'id'],
function($query) {
return $query->andWhere(['id_role' =>
RoleHelper::getConsultantRole()->id]);
});
But it's not a good solution. Why?
When you do a left join the id_role condition will make it inner join actually. The id_role condition should be placed inside ON section of the join.
I was searching the web plus inspecting the code but I don't see how it could be solved.
I got the answer from Qiang Xue - $query->onCondition() should be used for what I need. Result code:
return $this->hasMany(User::className(), ['id' => 'id_user'])
->from(User::tableName())
->viaTable(RoomActiveUser::tableName(), ['id_room' => 'id'],
function($query) {
$query->onCondition(['id_role' =>
RoleHelper::getConsultantRole()->id]);
});
Have you tried doing it like
->viaTable(RoomActiveUser::tableName(), ['id_room' => 'id', 'id_role' => RoleHelper::getConsultantRole()->id])
This should create a JOIN X on 'id_room' = 'id' AND 'id_role' = '$ConsultantRole_id'

CakePHP find with LEFT JOIN and generate_series

Basically, is it possible, and if so, how do you do the following code without using the raw query() method in CakePHP 2.0.6. I am using PostgreSQL (which generate_series() is a function of). So, how do you do this query the CakePHP way?
$sql = "
SELECT new_rank FROM generate_series(1,999) AS new_rank
LEFT JOIN tasks ON tasks.rank = new_rank
WHERE tasks.rank IS NULL LIMIT 1
";
$data = $this->Task->query($sql);
EDIT
One user said I could try to use the find call on Task and right join to generate_series(). Here is my attempt at that. This code throws an error, in that CakePHP is putting double quotes around the function arguments for generate_series. I wonder how I can get it to not do that?
$data = $this->Task->find('all', array(
'conditions' => array('Task.rank' => null),
'limit' => 1,
'recursive' => -1,
'fields' => 'new_rank',
'joins' => array(
array(
'table'=>'generate_series(1,999)',
'alias'=>'new_rank',
'type'=>'RIGHT',
'conditions' => array(
'tasks.rank'=>'new_rank'
)
)
)
));
Which products the following SQL:
SELECT "Task"."new_rank" AS "Task__new_rank"
FROM "tasks" AS "Task"
RIGHT JOIN generate_series("1,999") AS "new_rank" ON ("tasks"."rank" = 'new_rank')
WHERE "Task"."rank" IS NULL LIMIT 1
What you're probably looking for is in DboSource::expression(). It basically allows you to do a SQL expression without any of Cake's escaping. Make sure to sanitize inputs.
To have it show up as a field, you can try adding it to the fields key in your options array:
$ds = $this->Task->getDataSource();
$this->Task->find('all', array(
'fields' => $ds->expression('generate_series(1,999) AS new_rank')
));
If that doesn't work, you can always try DboSource::rawQuery() which doesn't escape anything, afaik.

Lots of queries to pull up user photos and their comments. (CakePHP)

What I'm trying to do is pull up profile info w/ the profile's comments. I get everything as expected. No error returned, array is formatted perfectly. My concern is the queries that are run. It runs one query for each ID to get its photo (the start of the query is noted in comments in the code below). I guess this is the only way to get photos by user_id? All in separate queries? Is there a better way?
I'm picturing a profile with 40+ comments and it's scary to imagine. Is this where memcached comes in?
$profile = $this->Profile->find('first', array(
'conditions' => array('Profile.url' => $url),
'contain' => array(
'User' => array(
'fields' => array(
'User.id','User.name'
),
'Photo' => array(
'fields' => array(
'Photo.thumbnail','Photo.image'
)
)
),
'Comment' => array(
'User' => array(
'fields' => array(
'User.name'
),
'Photo' => array( // right here
'fields' => array(
'Photo.thumbnail'
)
)
)
)
)
));
edit:
I obviously have a User table, as well as a Comment table. I also have a Photo table that stores URL's of the users images, foreign key = user_id. So while i query all Comments from a specific profile and it's Comment.user_id, I also need to grab the Photo.thumbnail from the Photo table by its user_id.
You can make it much faster using a LEFT JOIN.
edited code has been edited to better respond to the question (two left joins are needed - not one).
SELECT c.text, i.profiles, p.photo_url
FROM comments AS c
LEFT JOIN profiles AS i on c.profile_id = i.id
LEFT JOIN photos AS p ON i.id = p.user_id
WHERE c.post_id = 32
LIMIT 20
This is just a generic SQL but would:
pull all comments (in the comments table) bellowing to article 32
left join the profiles table matching the comment poster id to the comment
pull the first 20 comments
And with only one query you would pull all 30 comments + their associated profiles.
Hope it helps!
You can replace the array key 'contain' with the array key 'link', and it builds the left joins for you - see linkable behavior. The downside is that all relations linked must be from the hasOne or hasMany to the belongsTo relation.
You might also want to look at Nate's article in the Bakery about doing joins "the cake way".
http://bakery.cakephp.org/articles/view/quick-tip-doing-ad-hoc-joins-in-model-find

Categories