Дом, отдых, хобби
здравствуйте,нужна переписка задним числом,сможете помочь? - вопрос №2654793
ноябрь 12, 2017 г.
-
Всего ответов: 1
-
Здравствуйте. Сегодня мы научимся изменять дату отправки личных сообщений в социальной сети ВКонтакте. Хочу сказать сразу, что я не рассказываю что-то новое. В интернете полно аналогичных методов и я сам какие-то куски кода брал оттуда. Поэтому, не судите строго.
Итак, во первых, нам нужно иметь полный доступ к двум аккаунтам ВК. Например, первый аккаунт Ваш, а второй фэйковый. Во вторых, Вы должны иметь хоть какие-то азы в программировании. Но не волнуйтесь. Большую часть работы сделаю я сам. Все способы являются легкими и быстрыми в исполнении из-за «дыр» в данной социальной сети. Однако, нет гарантий, что каждый метод у Вас будет работать. Но хоть один точно сработает.
Начнем.
Первый способ. Метод вложенной переписки.
Алгоритм: создаем переписку, редактируем, меняем дату, отсылаем назад в виде пересылки.
Самым обычным способом, создаем переписку между двумя аккаунтами ВКонтакте. Подключаем каждый аккаунт к API. Для этого достаточно перейти по данной ссылке и разрешить сбор информации с аккаунта:В следствии, приложению будут доступны все данные пользователя. Не забудьте запомнить свой токен.
Далее, вытащим личные сообщения. Я буду использовать Python. Чтобы получить историю сообщений используем messages.getHistory [https://vk.com/dev/messages.getHistory]:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123# -*- coding: utf-8 -*-
import
codecs
import
ConfigParser
import
datetime
import
json
import
sys
import
urllib2
from
urllib
import
urlencode
import
vk_auth
def
_api(method, params, token):
params.append((
"access_token"
, token))
url
=
"<a href="https://api.vk.com/method/%s?%s">https://api.vk.com/method/%s?%s</a>"
%
(method, urlencode(params))
return
json.loads(urllib2.urlopen(url).read())[
"response"
]
# read config values
Config
=
ConfigParser.ConfigParser()
Config.read(
"config.ini"
)
login
=
Config.get(
"auth"
,
"username"
)
password
=
Config.get(
"auth"
,
"password"
)
messages_id
=
Config.get(
"messages"
,
"chat_id"
)
messages_type
=
Config.get(
"messages"
,
"chat_type"
)
app_id
=
Config.get(
"application"
,
"app_id"
)
# some chat preparation
if
messages_type
=
=
"interlocutor"
:
is_chat
=
False
elif
messages_type
=
=
"chat"
:
is_chat
=
True
else
:
sys.exit(
"Messages type must be either interlocutor or chat."
)
# auth to get token
try
:
token, user_id
=
vk_auth.auth(login, password, app_id,
'messages'
)
except
RuntimeError:
sys.exit(
"Incorrect login/password. Please check it."
)
sys.stdout.write(
'Authorized vk\n'
)
# get some information about chat
selector
=
"chat_id"
if
is_chat
else
"uid"
messages
=
_api(
"messages.getHistory"
, [(selector, messages_id)], token)
out
=
codecs.
open
(
'vk_exported_dialogue_%s%s.txt'
%
(
'ui'
if
not
is_chat
else
'c'
, messages_id),
"w+"
,
"utf-8"
)
human_uids
=
[messages[
1
][
"uid"
]]
# Export uids from dialogue.
# Due to vk.api, start from 1.
for
i
in
range
(
1
,
100
):
try
:
if
messages[i][
"uid"
] !
=
human_uids[
0
]:
human_uids.append(messages[i][
"uid"
])
except
IndexError:
pass
# Export details from uids
human_details
=
_api(
"users.get"
,
[(
"uids"
,
','
.join(
str
(v)
for
v
in
human_uids))],
token
)
human_details_index
=
{}
for
human_detail
in
human_details:
human_details_index[human_detail[
"uid"
]]
=
human_detail
def
write_message(who, to_write):
out.write(u
'[{date}] {full_name}:\n {message} \n\n\n'
.
format
(
*
*
{
'date'
: datetime.datetime.fromtimestamp(
int
(to_write[
"date"
])).strftime(
'%Y-%m-%d %H:%M:%S'
),
'full_name'
:
'%s %s'
%
(
human_details_index[who][
"first_name"
], human_details_index[who][
"last_name"
]),
'message'
: to_write[
"body"
].replace('
', '
\n')
}))
mess
=
0
max_part
=
200
# Due to vk.api
cnt
=
messages[
0
]
sys.stdout.write(
"Count of messages: %s\n"
%
cnt)
while
mess !
=
cnt:
# Try to retrieve info anyway
while
True
:
try
:
message_part
=
_api(
"messages.getHistory"
,
[(selector, messages_id), (
"offset"
, mess), (
"count"
, max_part), (
"rev"
,
1
)],
token
)
except
Exception as e:
sys.stderr.write(
'Got error %s, continue...\n'
%
e)
continue
break
try
:
for
i
in
range
(
1
,
201
):
write_message(message_part[i][
"uid"
], message_part[i])
except
IndexError:
break
result
=
mess
+
max_part
if
result > cnt:
result
=
(mess
-
cnt)
+
mess
mess
=
result
sys.stdout.write(
"Exported %s messages of %s\n"
%
(mess, cnt))
out.close()
sys.stdout.write(‘done!\n')
Далее, для простоты, поставим одну и ту же дату на все сообщения. Я не претендую на оптимизированный код и очевидно, что его можно ужать, но я хочу продемонстрировать как можно подробную работу парсера с подобными XML:
12345678910111213141516171819while
(
true
) {
doc = XDocument . Load(
"<a href="https://api.vk.com/method/messages.getHistory.xml?uid=12345&offset=">https://api.vk.com/method/messages.getHistory.xml?uid=12345&offset=</a>"
+ m +
"&count=200&access_token="
+ token);
foreach (XElement el in doc . Root . Elements()) {
if
(el . Name . ToString() ==
"message"
) {
foreach (XElement el_msg in el . Elements()) {
if
(el_msg . Name ==
"date"
) {
foreach (XElement el_date in el_msg . Elements()) {
if
(el_date . Name ==
" 1403320931"
) {
el_date . Name =
'1403429673'
;
// то есть меняем дату на любую другую
k++;
}
}
}
}
}
}
m +=
200
;
}
Я думаю, что основная идея здесь понятна. Осталось вернуть сообщения на сервер. Для этого нам понадобиться функция message.send(). Объект message должен обратиться к полю date, но сервер ВКонтакте устанавливает время у себя на сервере сам. Однако, если мы отправим сообщения как вложенную переписку — все получиться.
Наши письма должны имеют вложенную структуру, значит надо вызывать метод парсинга рекурсивно. Но в Java можно поступить проще. Всё, что находиться внутри цикла forEach, мы будем помещать в отдельный класс. В следствии, в методе accept будет происходить всё то, что было бы в теле цикла. В VkApiMessage есть поле fwd_messages. В нем будет хранится список из объектов пересланных сообщений VkApiMessage:
12345678910private
static
class
MessageConsumer
implements
Consumer<VKApiMessage> {
@Override
public
void
accept(VKApiMessage message) {}
}
messages.stream().forEach(
new
MessageConsumer());
if
(!message.fwd_messages.isEmpty()) {
System.out.println(
"<div class='wall'>"
);
message.fwd_messages.forEach(
new
MessageConsumer());
System.out.println(
"</div>"
);
}
Далее, просто отправляем сообщения назад на сервер. Здесь, думаю, все очевидно. Аналогично, можно легко использовать поле “attachment” объекта message. [https://vk.com/dev/messages.send]
В общем, результат выглядит ничем не хуже оригинала в ВК:
Второй способ. Метод изменения GMT на сервере.
Алгоритм: меняем время на сервере, отправляем сообщения.
Второй метод несколько легче первого, так как нам не нужно старые(но измененные) сообщения возвращать назад на сервер (кстати, иногда, это не получается сделать из-за “глупого” сервера). Второй же способ работает более надежно.
Здесь нам не нужны готовые сообщения. Мы их создадим сами и перешлем на сервер, предварительно изменив GMT (часовой пояс). Для таких целей нам понадобиться абузоустойчивый VPS. Желательно на базе CentOS.
Сначала, меняем время и дату на сервере. Опять же, это можно сделать любым другим способом. Можно так:
12345# mv /etc/localtime /etc/localtime.bak
ln
-s
/usr/share/zoneinfo/Europe/USA
/etc/localtime
# date MMDDhhmm
# date 03182015
# man date
Настраиваем наш сервер под данные сервера ВК:
IP:87.240.182.185
Browser: Mozilla/5.0 (compatible; vkShare; +http://vk.com/dev/Share)
Port: 36035
Host: srv185-182-240-87.vk.comНе забываем про регистрация на API (см. Первый способ). Отправляем сообщения через уже знакомую функцию message.send().
Объект message, описывающий личное сообщение, возвращает поле “date” — дата отправки сообщения в формате unixtime. Обратите внимание на фразу “дата отправки”. Ничего не говорится про дату получения сообщения сервером ВКонтакте. [https://vk.com/dev/message]
Вот и все. Результат аналогичный первому. Все очень просто.
Третий способ. Сниффер трафика.
Алгоритм: качаем/покупаем сниффер, радуемся.
Самый простой метод. Но, к сожалению, методика зависит от качества программы, которую мы качаем из интернета.
Итак, можно просто попробовать скачать/купить что-то типо Charles, словить запрос, редактировать его (дату) и дублировать. Программа перехватывает пакет, меняет время отправки внутри пакета и отправляет контакту. Сервис ВК получает уже заданное unixtime сообщение. Таких снифферов в интернете куча. Но качественных и бесплатных найти сложно. Однако, они стоят не так дорого.Как Вы уже поняли, отправить личное сообщение задним числом не составляет труда. Я не написал выше полностью все коды, а только самые необходимые и сложные. Дописать остальные, думаю, не составит труда. Большое спасибо.