Skip to content

Commit

Permalink
Merge pull request #4450 from xoriole/fix-channel-preview
Browse files Browse the repository at this point in the history
Various fixes for Tribler 7.3
  • Loading branch information
devos50 authored Apr 9, 2019
2 parents b42de3f + 73d37df commit e96d2f1
Show file tree
Hide file tree
Showing 15 changed files with 275 additions and 26 deletions.
6 changes: 4 additions & 2 deletions Tribler/Core/Libtorrent/LibtorrentMgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,9 @@ def get_metainfo(self, infohash_or_magnet, callback, timeout=30, timeout_callbac
infohash_bin = infohash_or_magnet if not magnet else parse_magnetlink(magnet)[1]
infohash = hexlify(infohash_bin)

if infohash in self.torrents:
if infohash in self.torrents and hasattr(self.torrents[infohash], 'handle'):
metainfo = {"info": lt.bdecode(get_info_from_handle(self.torrents[infohash].handle).metadata())}
callback(metainfo)
return

with self.metainfo_lock:
Expand Down Expand Up @@ -536,7 +538,7 @@ def got_metainfo(self, infohash, timeout=False):
metainfo["nodes"] = []
if peers and notify:
self.notifier.notify(NTFY_TORRENTS, NTFY_MAGNET_GOT_PEERS, infohash_bin, len(peers))
metainfo["initial peers"] = peers

metainfo["leechers"] = leechers
metainfo["seeders"] = seeders

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from Tribler.Core.Category.Category import default_category_filter
from Tribler.Core.Modules.MetadataStore.OrmBindings.channel_node import COMMITTED, LEGACY_ENTRY, NEW, PUBLIC_KEY_LEN, \
TODELETE, UPDATED
from Tribler.Core.Modules.MetadataStore.serialization import CHANNEL_TORRENT, ChannelMetadataPayload
from Tribler.Core.Modules.MetadataStore.serialization import CHANNEL_TORRENT, ChannelMetadataPayload, REGULAR_TORRENT
from Tribler.Core.TorrentDef import TorrentDef
from Tribler.Core.Utilities.tracker_utils import get_uniformed_tracker_url
from Tribler.Core.exceptions import DuplicateChannelIdError, DuplicateTorrentFileError
Expand Down Expand Up @@ -253,6 +253,18 @@ def get_torrent(self, infohash):
"""
return db.TorrentMetadata.get(public_key=self.public_key, infohash=infohash)

@db_session
def torrent_exists(self, infohash):
"""
Return True if torrent with given infohash exists in the user channel
:param infohash: The infohash of the torrent
:return: True if torrent exists else False
"""
return db.TorrentMetadata.exists(lambda g: g.metadata_type == REGULAR_TORRENT
and g.status != LEGACY_ENTRY
and g.public_key == self.public_key
and g.infohash == database_blob(infohash))

@db_session
def add_torrent_to_channel(self, tdef, extra_info=None):
"""
Expand Down Expand Up @@ -297,6 +309,10 @@ def add_torrent_to_channel(self, tdef, extra_info=None):
torrent_metadata = db.TorrentMetadata.from_dict(new_entry_dict)
return torrent_metadata

@db_session
def copy_to_channel(self, infohash):
return db.TorrentMetadata.copy_to_channel(infohash)

@property
def dirty(self):
return self.contents.where(lambda g: g.status in [NEW, TODELETE, UPDATED]).exists()
Expand Down
40 changes: 38 additions & 2 deletions Tribler/Core/Modules/MetadataStore/OrmBindings/torrent_metadata.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from __future__ import absolute_import

from binascii import hexlify
from binascii import hexlify, unhexlify
from datetime import datetime

from pony import orm
from pony.orm import db_session, desc, raw_sql, select

from Tribler.Core.Category.FamilyFilter import default_xxx_filter
from Tribler.Core.Modules.MetadataStore.OrmBindings.channel_node import LEGACY_ENTRY, TODELETE, UPDATED
from Tribler.Core.Modules.MetadataStore.OrmBindings.channel_node import LEGACY_ENTRY, NEW, TODELETE, UPDATED
from Tribler.Core.Modules.MetadataStore.serialization import REGULAR_TORRENT, TorrentMetadataPayload
from Tribler.Core.Utilities.tracker_utils import get_uniformed_tracker_url
from Tribler.Core.Utilities.utilities import is_channel_public_key, is_hex_string, is_infohash
from Tribler.pyipv8.ipv8.database import database_blob


Expand Down Expand Up @@ -71,6 +72,15 @@ def search_keyword(cls, query, lim=100):

fts_ids = raw_sql(
'SELECT rowid FROM FtsIndex WHERE FtsIndex MATCH $query ORDER BY bm25(FtsIndex) LIMIT $lim')

# TODO: Check for complex query
normal_query = query.replace('"', '').replace("*", "")
if is_hex_string(normal_query) and len(normal_query) % 2 == 0:
query_blob = database_blob(unhexlify(normal_query))
if is_channel_public_key(normal_query):
return cls.select(lambda g: g.public_key == query_blob or g.rowid in fts_ids)
if is_infohash(normal_query):
return cls.select(lambda g: g.infohash == query_blob or g.rowid in fts_ids)
return cls.select(lambda g: g.rowid in fts_ids)

@classmethod
Expand Down Expand Up @@ -217,4 +227,30 @@ def update_properties(self, update_dict):
self.timestamp = self._clock.tick()
self.sign()

@classmethod
@db_session
def copy_to_channel(cls, infohash, public_key=None):
"""
Create a new signed copy of the given torrent metadata
:param metadata: Metadata to copy
:return: New TorrentMetadata signed with your key
"""

existing = cls.get(public_key=public_key, infohash=infohash) if public_key \
else cls.select(lambda g: g.infohash == database_blob(infohash)).first()

if not existing:
return None

new_entry_dict = {
"infohash": existing.infohash,
"title": existing.title,
"tags": existing.tags,
"size": existing.size,
"torrent_date": existing.torrent_date,
"tracker_info": existing.tracker_info,
"status": NEW
}
return db.TorrentMetadata.from_dict(new_entry_dict)

return TorrentMetadata
8 changes: 7 additions & 1 deletion Tribler/Core/Modules/restapi/mychannel_endpoint.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import absolute_import

import base64
import codecs
import json
import logging
import os
from binascii import hexlify, unhexlify
Expand All @@ -18,7 +20,7 @@
import Tribler.Core.Utilities.json_util as json
from Tribler.Core.Modules.restapi.metadata_endpoint import SpecificChannelTorrentsEndpoint
from Tribler.Core.TorrentDef import TorrentDef
from Tribler.Core.Utilities.utilities import http_get
from Tribler.Core.Utilities.utilities import http_get, is_infohash, parse_magnetlink
from Tribler.Core.exceptions import DuplicateTorrentFileError
from Tribler.pyipv8.ipv8.database import database_blob

Expand Down Expand Up @@ -265,6 +267,10 @@ def _on_timeout(_):
deferred = http_get(uri)
deferred.addCallback(_on_url_fetched)
elif uri.startswith("magnet:"):
_, xt, _ = parse_magnetlink(uri)
if xt and is_infohash(codecs.encode(xt, 'hex')) \
and (my_channel.torrent_exists(xt) or my_channel.copy_to_channel(xt)):
return json.dumps({"added": 1})
try:
self.session.lm.ltmgr.get_metainfo(uri, callback=deferred.callback,
timeout=30, timeout_callback=_on_timeout, notify=True)
Expand Down
16 changes: 16 additions & 0 deletions Tribler/Core/Utilities/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,19 @@ def has_bep33_support():
Also see https://github.com/devos50/libtorrent/tree/bep33_support
"""
return 'dht_pkt_alert' in dir(libtorrent)


def is_infohash(infohash):
return infohash and len(infohash) == 40 and is_hex_string(infohash)


def is_channel_public_key(key):
return key and len(key) == 128 and is_hex_string(key)


def is_hex_string(text):
try:
int(text, 16)
return True
except ValueError:
return False
4 changes: 2 additions & 2 deletions Tribler/Test/Core/Libtorrent/test_libtorrent_mgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def test_get_metainfo(self):

def metainfo_cb(metainfo):
self.assertEqual(metainfo, {'info': {'pieces': ['a']}, 'leechers': 0,
'nodes': [], 'seeders': 0, 'initial peers': []})
'nodes': [], 'seeders': 0})
test_deferred.callback(None)

infohash = "a" * 20
Expand Down Expand Up @@ -152,7 +152,7 @@ def test_got_metainfo(self):

def metainfo_cb(metainfo):
self.assertDictEqual(metainfo, {'info': {'pieces': ['a']}, 'leechers': 0,
'nodes': [], 'seeders': 0, 'initial peers': []})
'nodes': [], 'seeders': 0})
test_deferred.callback(None)

fake_handle = MockObject()
Expand Down
34 changes: 34 additions & 0 deletions Tribler/Test/Core/Modules/MetadataStore/test_channel_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,40 @@ def test_add_torrent_to_channel(self):
self.assertTrue(channel_metadata.contents_list)
self.assertRaises(DuplicateTorrentFileError, channel_metadata.add_torrent_to_channel, tdef, None)

@db_session
def test_torrent_exists_in_channel(self):
"""
Test torrent already exists in the channel.
"""
channel_metadata = self.mds.ChannelMetadata.create_channel('test', 'test')
self.mds.TorrentMetadata.from_dict(dict(self.torrent_template, infohash="1"))
self.assertTrue(channel_metadata.torrent_exists("1"))
self.assertFalse(channel_metadata.torrent_exists("0"))

@db_session
def test_copy_to_channel(self):
"""
Test copying a torrent from an another channel.
"""
self.mds.ChannelNode._my_key = default_eccrypto.generate_key('low')
channel1 = self.mds.ChannelMetadata(infohash=str(random.getrandbits(160)))
self.mds.TorrentMetadata.from_dict(dict(self.torrent_template, infohash="1"))

self.mds.ChannelNode._my_key = default_eccrypto.generate_key('low')
channel2 = self.mds.ChannelMetadata(infohash=str(random.getrandbits(160)))

# Trying copying existing torrent to channel
new_torrent = channel2.copy_to_channel("1")
self.assertIsNotNone(new_torrent)
self.assertEqual(1, len(channel1.contents_list))
self.assertEqual(1, len(channel2.contents_list))

# Try copying non-existing torrent ot channel
new_torrent2 = channel2.copy_to_channel("2")
self.assertIsNone(new_torrent2)
self.assertEqual(1, len(channel1.contents_list))
self.assertEqual(1, len(channel2.contents_list))

@db_session
def test_restore_torrent_in_channel(self):
"""
Expand Down
29 changes: 29 additions & 0 deletions Tribler/Test/Core/Modules/MetadataStore/test_torrent_metadata.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import

import codecs
import random
from datetime import datetime

Expand Down Expand Up @@ -135,6 +136,34 @@ def test_stemming_search(self):
results = self.mds.TorrentMetadata.search_keyword("sheeps")[:]
self.assertEqual(torrent.rowid, results[0].rowid)

@db_session
def test_infohash_search(self):
"""
Test searching for torrents with infohash works.
"""
infohash = b"e84213a794f3ccd890382a54a64ca68b7e925433"
torrent = self.mds.TorrentMetadata.from_dict(dict(rnd_torrent(), infohash=codecs.decode(infohash, 'hex'),
title="mountains sheep", tags="video"))

# Search with the hex encoded infohash
query = '"%s"*' % infohash
results = self.mds.TorrentMetadata.search_keyword(query)[:]
self.assertEqual(torrent.rowid, results[0].rowid)

@db_session
def test_channel_public_key_search(self):
"""
Test searching for channels with public key works.
"""
self.mds.ChannelNode._my_key = default_eccrypto.generate_key('curve25519')
channel = self.mds.ChannelMetadata(title='My channel', infohash=str(random.getrandbits(160)))

# Search with the hex encoded channel public key
query = '"%s"*' % codecs.encode(channel.public_key, 'hex')
results = self.mds.TorrentMetadata.search_keyword(query)[:]
self.assertIsNotNone(results)
self.assertTrue(channel.rowid, results[0].rowid)

@db_session
def test_get_autocomplete_terms(self):
"""
Expand Down
24 changes: 23 additions & 1 deletion Tribler/Test/Core/Utilities/test_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from twisted.web.util import Redirect

from Tribler.Core.Utilities.network_utils import get_random_port
from Tribler.Core.Utilities.utilities import http_get, is_simple_match_query, is_valid_url, parse_magnetlink
from Tribler.Core.Utilities.utilities import http_get, is_channel_public_key, is_infohash, is_simple_match_query, \
is_valid_url, parse_magnetlink
from Tribler.Test.test_as_server import AbstractServer
from Tribler.Test.tools import trial_timeout

Expand Down Expand Up @@ -82,3 +83,24 @@ def test_simple_search_query(self):

query2 = '"\xc1ubuntu"* OR "debian"*'
self.assertFalse(is_simple_match_query(query2))

def test_is_infohash(self):
hex_40 = "DC4B96CF85A85CEEDB8ADC4B96CF85A85CEEDB8A"
self.assertTrue(is_infohash(hex_40))

hex_not_40 = "DC4B96CF85A85CEEDB8ADC4B96CF85"
self.assertFalse(is_infohash(hex_not_40))

not_hex = "APPLE6CF85A85CEEDB8ADC4B96CF85A85CEEDB8A"
self.assertFalse(is_infohash(not_hex))

def test_is_channel_public_key(self):
hex_128 = "224b20c30b90d0fc7b2cf844f3d651de4481e21c7cdbbff258fa737d117d2c4ac7536de5cc93f4e9d5" \
"1012a1ae0c46e9a05505bd017f0ecb78d8eec4506e848a"
self.assertTrue(is_channel_public_key(hex_128))

hex_not_128 = "DC4B96CF85A85CEEDB8ADC4B96CF85"
self.assertFalse(is_channel_public_key(hex_not_128))

not_hex = "APPLE6CF85A85CEEDB8ADC4B96CF85A85CEEDB8A"
self.assertFalse(is_channel_public_key(not_hex))
22 changes: 14 additions & 8 deletions TriblerGUI/qt_resources/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -3736,19 +3736,25 @@ font-weight: bold;</string>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>8</width>
<width>12</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="channel_preview_label">
<widget class="QPushButton" name="channel_preview_label">
<property name="toolTip">
<string extracomment="reload preview"/>
</property>
<property name="styleSheet">
<string notr="true">color: #eee; font-size: 15px;</string>
</property>
<property name="text">
<string>Preview</string>
<string>Preview ⟳</string>
</property>
<property name="margin">
<number>8</number>
</property>
</widget>
</item>
Expand Down Expand Up @@ -4421,7 +4427,7 @@ border-top: 1px solid #555;
<rect>
<x>0</x>
<y>0</y>
<width>755</width>
<width>300</width>
<height>646</height>
</rect>
</property>
Expand Down Expand Up @@ -4505,7 +4511,7 @@ color: white;</string>
<item row="1" column="0">
<widget class="QLabel" name="label_37">
<property name="text">
<string>Family filter enabled?
<string>Family filter enabled?
(requires Tribler restart)</string>
</property>
</widget>
Expand Down Expand Up @@ -7897,15 +7903,15 @@ margin-right: 10px;</string>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="toolTip">
<string>Click to copy magnet link</string>
</property>
<property name="styleSheet">
<string notr="true">border: none;</string>
</property>
<property name="text">
<string/>
</property>
<property name="toolTip">
<string>Click to copy magnet link</string>
</property>
<property name="icon">
<iconset>
<normaloff>../images/magnet.png</normaloff>../images/magnet.png</iconset>
Expand Down
3 changes: 3 additions & 0 deletions TriblerGUI/qt_resources/torrent_details_container.ui
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ QTabBar::tab:selected {
<property name="text">
<string>00000000000000000000</string>
</property>
<property name="textInteractionFlags">
<set>Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="1">
Expand Down
Loading

0 comments on commit e96d2f1

Please sign in to comment.